Проблема вращения Arcball с масштабом и переводом - PullRequest
0 голосов
/ 18 ноября 2018

Я недавно реализовал руководство по аркболу здесь: https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Arcball в моем проекте, и у меня возникли некоторые проблемы с масштабированием и переводом объектов.

Проблема: при масштабировании и перемещении вращение дает неверный вывод, например, изгибание внутрь или увеличение частей объекта под определенными углами. Однако , когда я применяю масштабирование и перевод непосредственно к вершинам моего объекта, вращение работает. То есть в рабочем состоянии моя модельная матрица для этого объекта является единичной матрицей. Что-нибудь еще, и это не удается. Так что я точно знаю, что это порядок, в котором они применяются. Я просто не уверен, какой порядок. Применение перевода и масштабирования наряду с вращением в порядке TRS также не помогло и дало неправильный результат.

РЕДАКТИРОВАТЬ: Исправлены проблемы перевода и масштабирования, но объект не вращается относительно измененного центра. Вращается относительно старого центра.

Соответствующий код:

Деталь из объекта отрисовка кода:

if (R.mouseMoved) {
    glm::vec3 va = get_arcball_vector(R.click_mx, R.click_my);
    glm::vec3 vb = get_arcball_vector(R.cur_mx, R.cur_my);
    float ang = glm::degrees(acos(min(1.0f, glm::dot(va, vb)))) * MMOVE_FACTOR * R.deltaTime;
    glm::vec3 axis_in_camera_coord = glm::cross(va, vb);
    glm::mat3 camera2object = glm::inverse(glm::mat3(R.view) * glm::mat3(model));
    glm::vec3 rotaxis = camera2object * axis_in_camera_coord;
    model = glm::rotate(model, ang, rotaxis);
}

// assuming this is what I needed to do here for view matrix, TRT, this doesn't work
glm::mat4 mv = /*glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -WINDOW_X * .5)) * */R.view * model/* * glm::translate(glm::mat4(1.0f), -center)*/;
glm::mat4 pvm = Renderer::proj * mv;

pvm = glm::translate(pvm, translation);
pvm = glm::scale(pvm, scale);

Сразу после этого матрица pvm отправляется в шейдер, и объект отображается.

Функция векторного вычисления:

glm::vec3 get_arcball_vector(int x, int y) {
    glm::vec3 P = glm::vec3(1.0*x / WINDOW_X * 2 - 1.0,
        1.0*y / WINDOW_Y * 2 - 1.0,
        0);
    P.y = -P.y;
    float OP_squared = P.x * P.x + P.y * P.y;
    if (OP_squared <= 1 * 1)
        P.z = sqrt(1 * 1 - OP_squared);  // Pythagoras
    else
        P = glm::normalize(P);  // nearest point
    return P;
}

MMOVE_FACTOR равен 0,05, а R.deltaTime регулирует время рендеринга и движения мыши, чтобы сделать ее более плавной. Рассматриваемый объект может иметь произвольное масштабирование и перевод, чтобы он появлялся в разных местах сцены. Независимо от того, что я пробовал, это не дает желаемого результата. Например, я пробовал следующее:

        model = glm::translate(model, -center);
        model = glm::rotate(model, glm::degrees(ang), rotaxis);
        model = glm::translate(model, center);

Но это также не дает хороших результатов, и вращение все еще неправильное.

РЕДАКТИРОВАТЬ 2: В соответствии с предложением httpdigest, вот последний код:

glm::mat4 tr = glm::translate(glm::mat4(1.0f), -R.camera.getPos());
glm::mat4 trc = glm::translate(glm::mat4(1.0f), -center);
glm::mat4 tmc = glm::translate(glm::mat4(1.0f), center);
glm::mat4 rx = glm::rotate(glm::mat4(1.0f), -(float)R.camera.getPitch(), glm::vec3(1.0, 0, 0));
glm::mat4 ry = glm::rotate(glm::mat4(1.0f), (float)R.camera.getYaw(), glm::vec3(0, 1.0, 0));
glm::mat4 pvm = Renderer::proj * tr * rx * ry * trc * tmc;

pvm = glm::translate(pvm, translation);
pvm = glm::scale(pvm, scale);

Центр - это glm :: vec3 с суммой вершин, деленной на количество вершин.

Проблема с вышесказанным: это не работает правильно с переводами вокруг оси X. Когда я поворачиваю его настолько, что думаю, что он находится на том же расстоянии, что и значение перевода, он правильно вращается по оси Y. Другая проблема состоит в том, что это не ведет себя как аркбол, но я предполагаю, что это ожидается от того, как обрабатываются вращения. Хотя я могу ошибаться.

...