Проблема вращения Arcball с масштабом и переводом

Я недавно реализовал руководство по аркболу здесь: 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. Другая проблема состоит в том, что это не ведет себя как аркбол, но я предполагаю, что это ожидается от того, как обрабатываются вращения. Хотя я могу ошибаться.

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …