OpenGL - Невозможно получить совокупное вращение вокруг правильной оси и начала координат. - PullRequest
2 голосов
/ 27 октября 2019

Я реализую ротацию Arcball в существующем проекте, который я написал несколько лет назад, используя OpenTK & C #, и застрял на последнем препятствии.

Это не-шейдерный OpenGL «старого стиля»,Я уверен, что вращение Arcball работает правильно, проблема заключается только в применении полученной матрицы. Это должно быть довольно просто, но это не сработает.

Я получаю вращение Arcball как кватернион (qCurrent), а затем преобразую его в матрицу. Затем я попробовал несколько подходов:

  1. Просто примените это как дополнительный поворот к существующей сцене:

    GL.PushMatrix();
    Matrix4 arcball_rot = Matrix4.CreateFromQuaternion(qCurrent);
    GL.MultMatrix(ref arcball_rot);
    ... render objects in scene
    GL.PopMatrix();
    

Это относитсяправильное вращение вокруг правильного начала координат (цели камеры), но относительно мировой системы координат, а не зрителя. Это имеет смысл, потому что я эффективно применяю вращения в неправильной последовательности.

Применять повороты по порядку, сначала вращение дуги, что означает начинать с нуля. Здесь rtn_complete - это матрица, хранящая матрицу вида модели как инициализированную до вращения Arcball:

Matrix4 modelview = Matrix4.LookAt(camera.camerapos, camera.cameratarget, camera.cameraup);
rtn_complete = modelview;

Тогда ...

Matrix4 mm = Matrix4.CreateFromQuaternion(qCurrent) * rtn_complete;
GL.LoadIdentity();
GL.MultMatrix(ref mm);

Это применяется правильновращение относительно зрителя, но вокруг неправильного центра вращения. Это точка, находящаяся далеко от цели камеры.

Очевидно, что для этого подхода требуется сдвиг вперед / назад по обе стороны от поворота, но я попробовал почти все возможные комбинации из них, и ни одна из них не сработала.

Положение камеры и цели: -

camera.camerapos = (-51,3, -67,9, 37,7) и

camera.cameratarget = (0,0,0.6, 7.3)

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

GL.LoadIdentity();
GL.Translate(camera.cameratarget);
GL.MultMatrix(ref arcball_rot);
GL.Translate(-camera.cameratarget);
GL.MultMatrix(ref rtn_complete);

Мне кажется, что кореньВероятно, проблема заключается в переводе, примененном с помощью LookAt, который я не учитываю при выполнении вышеуказанных преобразований.

Однако, когда я проверяю матрицу rtn_complete (которая является матрицей просмотра модели после LookAt),четвертый столбец не содержит перевода. Матрица выглядит следующим образом:

0.80, 0.20, -0.56, 0.00
-0.60, 0.27, -0.75, 0.00
0.00, 0.94, 0.34, 0.00
0.38, -7.02, -92.8, 1.00

Я бы ожидал увидеть здесь перевод.

РЕДАКТИРОВАТЬ 1:

Найден в конце концов. Я был на правильном пути с моим подозрением о переводе, полученном в результате использования Matrix4.LookAt ().

Способ, которым я перечислил матрицы для отладки, привел к транспонированию, так что перевод был для меня, чтобы увидетьно я скучал по нему, но это было в четвертом ряду, а не в четвертом столбце. Перевод: (0,38, -0,72, -92,8). Применение этого перевода по обе стороны от поворота Аркбола первоначально приводит к ожидаемому поведению поворота.

GL.LoadIdentity();
GL.Translate(0.38, -7.02, -92.8);
GL.MultMatrix(ref mm);
GL.Translate(-0.38, 7.02, 92.8);
GL.MultMatrix(ref rtn_complete);

РЕДАКТИРОВАТЬ 2:

ИмеяВыяснив вышесказанное, я очень близок, но это все еще не совсем правильно, когда я переезжаю куда-то еще на сцену. Снова у меня есть пара проблем, и я могу решить одну или другую, но не одновременно обе. 'и' rtn_complete_rot ').

Если я это сделаю, повороты будут точно:

GL.LoadIdentity();
GL.Translate(rtn_complete_trans); // modelview translation component
GL.Translate(camera.cameratarget); // translate to rotation centre
GL.MultMatrix(ref arcball_rot); // ongoing Arcball rotation
GL.MultMatrix(ref rtn_complete_rot); // modelview rotation component
GL.Translate(-camera.cameratarget); // translate back from rotation centre

Но при каждом инициализации представления происходит нежелательный перевод. Если я поверну, отпущу и повторю несколько раз, объект постепенно смещается с экрана.

Если я изменяю положение второй камеры, это нежелательное смещение больше не происходит, но центр вращения выключен:

GL.LoadIdentity();
GL.Translate(rtn_complete_trans); // modelview translation component
GL.Translate(camera.cameratarget); // translate to rotation centre
GL.MultMatrix(ref arcball_rot); // ongoing Arcball rotation
GL.Translate(-camera.cameratarget); // translate back from rotation centre
GL.MultMatrix(ref rtn_complete_rot); // modelview rotation component

Кто-нибудь может объяснить?

...