Как бы вы создали эффект прокрутки для объекта? - PullRequest
0 голосов
/ 19 октября 2018

Я использую OpenGL в Visual C ++ и отображаю прямоугольник с использованием VBO и VAO, и у меня есть базовый вершинный шейдер и фрагментный шейдер, чтобы применить цвет и положение для объекта.

Я хотел бы создать эффект прокрутки объекта, пока я не нажму клавишу Esc .Каков был бы лучший способ сделать это?

Я знаю, что вы можете предоставить свои матрицы Model, View и Projection для вашего шейдера для выполнения изменений объекта.Особенно модель матрицы для выполнения преобразований.Я могу изменить положение объекта и повернуть его, но я не уверен, как создать непрерывный или прокручивающий эффект перемещения объекта или вращения до нажатия клавиши.

Мой код пока:

GLfloat vb_data[] = {
    -0.25f, 0.25f, 0.0f, // Top-left
    0.25f, 0.25f, 0.0f, // Top-right
    0.25f, -0.25f, 0.0f, // Bottom-right
    -0.25f, -0.25f, 0.0f  // Bottom-left
};
glGenBuffers(1, &vbo_ID);
glBindBuffer(GL_ARRAY_BUFFER, vbo_ID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vb_data), vb_data, GL_DYNAMIC_DRAW);
GLfloat incre = 0.01f;


glClear(GL_COLOR_BUFFER_BIT);

while (1){
    glm::mat4 trans = glm::mat4(1.0f);
    glm::mat4 transBar = glm::translate(trans, glm::vec3(0.2f, 0.2f, 1.0f));
    glm::mat4 MVP = transBar;

    glUseProgram(pgID);
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
    glBindBuffer(GL_ARRAY_BUFFER, vbo_ID);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(
        0,                   
        3,                  
        GL_FLOAT,           
        GL_FALSE,           
        0,                  
        (void*)0           
        );

    glDrawArrays(GL_QUADS,0, 4);

    glDisableVertexAttribArray(0);
    SwapBuffers(g_pOpenGLWindow->hDC);
}

1 Ответ

0 голосов
/ 21 октября 2018

, но я не уверен, как создать непрерывный или прокручивающий эффект перемещения объекта или вращения ...

Чтобы создать плавное движение (перемещение или вращение),Перемещаемая или вращающаяся часть матрицы модели должна быть изменена на небольшую величину соответственно на угол в каждом кадре.Это может быть достигнуто с помощью управляющих переменных, которые увеличиваются с небольшим шагом в каждом кадре.Модельная матрица должна быть пересчитана путем использования этих управляющих переменных в каждом кадре.
См. Концепцию в следующем псевдокоде:

translate_x = 0;
angle       = 0;

while (1)

    model_matrix = translate(translate_x, 0, 0) * roatateX(angle)

    translate_x = translate_x + step_x
    angle       = angle + step_angle

Попробуйте следующий код и поиграйтесь с параметрами, для достижения эффекта для ваших нужд:

float angle        = 0.0f;
float step_ang     = 1.0f;
float trans_x      = -0.5f;
float step_x       = 0.01f;
bool  move_forward = true;
while (1)
{
    glm::mat4 model = glm::mat4(1.0f);
    model = glm::translate(model, glm::vec3(trans_x, 0.2f, 1.0f));
    model = glm::rotate(model, glm::radians(angle), glm::vec3(0.0f, 0.0f, 1.0f));

    angle        += step_ang;
    trans_x      += move_forward ? step_x : -step_x;
    move_forward  = move_forward ? trans_x < 0.5f : trans_x <= -0.5f;

    glm::mat4 MVP = model;

    .....

... до нажатия клавиши.

Поскольку вопрос помечен winapi , я предполагаю, что вы инициализировали WNDCLASSEX структуру данных и что для функции WindowProc установлена ​​функция lpfnWndProc.

Вы должны реализовать событие сообщения WM_KEYDOWN в функции обратного вызова окна и проверить, была ли нажата Esc (VK_ESCAPE):

глобальная переменная:

bool esc_pressed = false;

функция обратного вызова:

LRESULT CALLBACK WindowProcedure( HWND hWnd, unsigned int msg, WPARAM wparam, LPARAM lparam )
{
    switch(msg)
    {
        case WM_KEYDOWN:
            if ( wparam == VK_ESCAPE )
                esc_pressed = true;
            break;

        // other messages
        // ...
    }
    return DefWindowProc( hWnd, msg, wparam, lparam );
}

Далее вам придется обрабатывать оконные сообщения в основном цикле.См. Функции GetMessage и DispatchMessage.

вместо

while (1)
{
    .....
}

вам необходимо

MSG msg;
while( GetMessage( &msg, 0, 0, 0 ) )
{
    DispatchMessage( &msg );

    .....
}
...