Переместить модель в OpenGL с помощью матрицы перевода вместо glTranslate () - PullRequest
0 голосов
/ 13 февраля 2019

Моя цель - перемещение объекта нажатием клавиш со стрелками.Для этого в обратном вызове я создаю матрицу перевода из некоторого смещения и умножаю ее на мировую матрицу.Однако это не работает - куб не двигается нажатием клавиш.Я также заметил, что использование glTranslate () напрямую с установленным смещением работает хорошо, но выглядит как костыль.Я имею в виду, я должен использовать только матрицы перевода для любого преобразования модели.Где проблема в моем коде?Как это исправить?Почему glTranslate () работает хорошо?Пример минимального кода:


glm::mat4 mWorldMatrix;
glm::mat4 mViewMatrix;
glm::mat4 mProjMatrix;

void onKeyCallback(GLFWwindow*, int key, int scan, int action, int mods)
{
    switch (key)
    {
        case GLFW_KEY_UP:
        {
            auto translationMatrix = glm::translate(glm::mat4{}, glm::vec3{ 0, 1, 0 });
            mWorldMatrix = mWorldMatrix * translationMatrix;
            break;
        }
        case GLFW_KEY_DOWN:
        {
            auto translationMatrix = glm::translate(glm::mat4{}, glm::vec3{ 0, -1, 0 });
            mWorldMatrix = mWorldMatrix * translationMatrix;
            break;
        }
        case GLFW_KEY_LEFT:
        {
            auto translationMatrix = glm::translate(glm::mat4{}, glm::vec3{ -1, 0, 0 });
            mWorldMatrix = mWorldMatrix * translationMatrix;
            break;
        }
        case GLFW_KEY_RIGHT:
        {
            auto translationMatrix = glm::translate(glm::mat4{}, glm::vec3{ 1, 0, 0 });
            mWorldMatrix = mWorldMatrix * translationMatrix;
            break;
        }
    }
}


int main()
{
    glfwInit();

    const int weight = 640;
    const int height = 480;
    auto mWindow = glfwCreateWindow(weight, height, "TesT", nullptr, nullptr);
    glfwMakeContextCurrent(mWindow);

    glShadeModel(GL_SMOOTH);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    mWorldMatrix = glm::mat4{ 1.0f };
    mViewMatrix = glm::lookAt(glm::vec3{ 0, 0, -1 },
                              glm::vec3{ 0, 0, 0 },
                              glm::vec3{ 0, 1, 0 });
    mProjMatrix = glm::perspective(glm::radians(45.0f),
                                   static_cast<float>(weight) / height, 
                                   0.1f, 
                                   100.0f);

    glfwSetKeyCallback(mWindow, onKeyCallback);

    while (!glfwWindowShouldClose(mWindow)) {
        glClearColor(0.5, 0.5, 0.5, 0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glViewport(0,0, weight, height);

        auto modelViewMatrix = mViewMatrix * mWorldMatrix;
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(static_cast<const float*>(glm::value_ptr(modelViewMatrix)));

        glMatrixMode(GL_PROJECTION_MATRIX);
        glLoadMatrixf(static_cast<const float*>(glm::value_ptr(mProjMatrix)));

        Cube cube{ glm::vec3{0.5, 0.5, 0.5}, 1 }; //cube with center in {0.5} and side length 1
        auto vertices = cube.soup(); //vector of vertex

        glTranslatef(0 /* + offset.x*/, 0/* + offset.y*/, -5); //Setting offset here is work good
        glBegin(GL_TRIANGLES);
        for (const auto& vertex : vertices)
        {
            glColor3f(vertex.position.x, vertex.position.y, vertex.position.z);
            glVertex3f(vertex.position.x, vertex.position.y, vertex.position.z);
        }
        glEnd();

        glfwSwapBuffers(mWindow);
        glfwWaitEvents();
    }

    glfwTerminate();
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Обратите внимание, что рисование с помощью glBegin / glEnd последовательностей, а также стека матрицы фиксированных функций и фиксированной функции.См. конвейер с фиксированными функциями и Legacy OpenGL .Прочитайте о Спецификации вершин и Шейдер , чтобы узнать о современном способе рендеринга.


Матрица проекции должна быть применена к стеку матриц проекции иматрица представления модели в стек матрицы представления модели.

Есть 2 проблемы.

  1. GL_PROJECTION_MATRIX не является допустимой константой перечисления для glMatrixMode и приведет к ошибке GL_INVALID_ENUM.Допустимая константа перечисления для режима матрицы проекции - GL_PROJECTION.GL_PROJECTION_MATRIX будет использоваться для считывания текущей матрицы проекции по glGetFloatv.

  2. Если вы хотите применить дополнительное преобразование к модели, то вам необходимовыберите матрицу GL_MODELVIEW раньше.Если матрица GL_PROJECTION выбрана, это состояние сохраняется до тех пор, пока оно не будет снова явно изменено.

glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(static_cast<const float*>(glm::value_ptr(modelViewMatrix)));

glMatrixMode(GL_PROJECTION); // <----- `GL_PROJECTION` instead of `GL_PROJECTION_MATRIX`
glLoadMatrixf(static_cast<const float*>(glm::value_ptr(mProjMatrix)));

// [...]

glMatrixMode(GL_MODELVIEW); // <-------- specify `GL_MODELVIEW`
glTranslatef(0 /* + offset.x*/, 0/* + offset.y*/, -5); //Setting offset here is work good
0 голосов
/ 13 февраля 2019

Потому что в каждом цикле вы устанавливаете куб в исходное положение.Вы должны определить эти объекты вне цикла.Затем вы можете изменять их в цикле while.

На уроках openGL в университете я очень часто использовал серию YouTube из «Черно».Он сделал курс openGL .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...