Смещение мировых координат в OpenGL

360
03 ноября 2017, 11:06

Всем доброго времени суток. Отлавливаю клики мыши, затем преобразую каждый клик, который является центром примитива, в некоторый набор точек. Каждый набор состоит из 3-х точек (примитив - треугольник), каждая точка задаётся 3-мя координатами. Т.к. я использую ортогональную проекцию - координаты хранятся в пиксельном виде. Так же запоминаю позицию каждого центра. В игровом цикле модельную матрицу переношу в центр фигуры, которая рисуется.

Проблема в следующем: когда я кликаю первый раз - фигура рисуется так, как и нужно. Второй и последующий разы уже рисуются так, будто бы начало моих координат установилось в точке, где был первый клик. Я понимаю, что где-то нужно матрицу делать единичной, но не могу понять где. Как я понимаю, это происходит уже в мировых координатах - их начало координат смещается после первого клика.

Использую:

  • glfw для контекста,
  • glew для функций openGL
  • glm для операций над модельной матрицей

Обработка клика мыши:

if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
{
    double xpos, ypos;
    glfwGetCursorPos(window, &xpos, &ypos);
    cout << "Координаты : x: " << xpos << " ; y: " << ypos << endl;
    float left = 0.0f;
    float right = 800.0f;
    float bottom = 0.0f;
    float top = 600.0f;
    float x = ((xpos / WIDTH) * (right - left)) + left;
    float y = ((ypos / HEIGHT) * (bottom - top)) + top;
    cout << "Координаты openGL: x: " << x << " ; y: " << y << endl;
    GLfloat upd[] = {
        x - param, y - param, -1.0f,
        x, y + param, -1.0f,
        x + param, y - param, -1.0f,
    };
    //number of primitives:
    numVertices++;
    GLintptr vertexOffset = (numVertices-1) * sizeof(upd);
    glBufferSubData(GL_ARRAY_BUFFER, vertexOffset, sizeof(upd), upd);
    GLfloat posX1 = x;
    GLfloat posY1 = y;
    GLfloat posZ1 = -1.0f;
    glm::vec3 newPosition = glm::vec3(posX1, posY1, posZ1);
    position[numVertices-1] = newPosition;
}

Настройки параметров и рисование:

glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow * window = glfwCreateWindow(800, 600, "Learn OpenGL", nullptr, nullptr);
if (window == nullptr)
{
    std::cout << "Ошибка при создании окна GLFW!" << std::endl;
    glfwTerminate();
    return -1;
}
glfwMakeContextCurrent(window);
if (window == nullptr) return -1;
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
    return -1;  
int width_t, heigth_t;
glfwGetFramebufferSize(window, &width_t, &heigth_t);
glViewport(0, 0, width_t, heigth_t);

//устанавливаем callback-функции (регистрация идёт ПОСЛЕ создания окна и ДО запуска игрового цикла):
glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
ShadersFor1_2Lab ourShader("shader.vs", "shader.frag");
GLuint VAO, VBO;
GLsizeiptr vertexBufferSize = 10 * 3 * 3 * sizeof(GLfloat);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertexBufferSize, NULL, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);

//игровой цикл:
while (!glfwWindowShouldClose(window))
{
    glfwPollEvents(); //проверяет, вызвано ли какое-либо событие. и если да - исполняет его
    //glEnable(GL_DEPTH_TEST);
    glClearColor(1.0f, 1.0f, 1.0f, .1f);    //устанавливает состояние
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     //использует состояние
    ourShader.Use();
    GLint projectionLoc = glGetUniformLocation(ourShader.Program, "projection"),
        viewLoc = glGetUniformLocation(ourShader.Program, "view"),
        modelLoc = glGetUniformLocation(ourShader.Program, "model");
    glm::mat4 view(1.0);
    view = glm::translate(view, glm::vec3(0.0f, 0.0f, -2.0f));
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glm::mat4 projection(1.0);
    projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);
    glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
    glBindVertexArray(VAO);
    glm::mat4 model(1.0f);
    for (GLuint i = 0; i < position.size(); i++)
    {
        glm::mat4 model(1.0);
        model = glm::translate(model, position[i]);
        glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }
    glBindVertexArray(0);
    glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
Answer 1

В цикле

for (GLuint i = 0; i < position.size(); i++)
{
    glm::mat4 model(1.0);
    model = glm::translate(model, position[i]);
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    glDrawArrays(GL_TRIANGLES, 0, 3);
}

вы для i-го треугольника используете свою матрицу модели, но рисуете первые три вершины из буфера, которые соответствуют нулевому треугольнику. Нужно вторым параметром указывать смещение в буфере:

glDrawArrays(GL_TRIANGLES, i * 3, 3);

Еще несколько настораживает то, что здесь

float x = ((xpos / WIDTH) * (right - left)) + left;
float y = ((ypos / HEIGHT) * (bottom - top)) + top;
cout << "Координаты openGL: x: " << x << " ; y: " << y << endl;
GLfloat upd[] = {
    x - param, y - param, -1.0f,
    x, y + param, -1.0f,
    x + param, y - param, -1.0f,
};

вы задаете позиции вершины треугольника в мировых координатах смещенными на (x; y), а затем в цикле загружаете в шейдер матрицу модели, которой еще раз двигаете треугольник на (x; y). Чему равны WIDTH и HEIGHT?

READ ALSO
напишите мне пожалуйста програмку [требует правки]

напишите мне пожалуйста програмку [требует правки]

Описать структуру ABITURIENT со следующими полями:

279
Ввод строки в c++

Ввод строки в c++

Подскажите пожалуйста, правильно ли я реализовал ввод строки?

348
Как в JQuery реализовать проверку на волидность, если на форме 3 кнопки и для каждой существует свое правило?

Как в JQuery реализовать проверку на волидность, если на форме 3 кнопки и для каждой существует свое правило?

На странице JSP находиться форма для добавления данных в БД с 3 кнопками (Add,Update,Delete)

221