Проблема преобразования OpenGL ES arcball - PullRequest
0 голосов
/ 28 декабря 2010

Я перенес классы аркбола, которые я использовал, с vb.net на iPhone, используя цель C ++, но теперь у меня проблема. Когда я вращаю свой объект, все в порядке. Как только я поворачиваю вид, мой центр вращения больше не находится в центре происхождения моих объектов, как это было раньше. В идеале я хотел бы иметь возможность установить, где в системе координат объектов находится точка вращения. Я не уверен, где в рутине аркбола я должен был внести изменения, чтобы сделать это. Реализация, на которой я основывался, находится по ссылке ниже:

http://www.codeproject.com/KB/openGL/Tao_Arcball.aspx

Я сделал небольшое изменение в том, как он себя ведет, и преобразовал его в сенсорный интерфейс, но то, как он работает, остается тем же, что и эта реализация, что касается проблемы, с которой я столкнулся.

Эти ссылки объясняют еще кое-что по математике за кватернионами и поворотами матриц:

http://www.j3d.org/matrix_faq/matrfaq_latest.html http://www.gamedev.net/reference/articles/article1095.asp http://en.wikipedia.org/wiki/Quaternion_rotation

Основная часть кода, которую, я думаю, нужно будет изменить, приведена ниже (в vb.net):

        Public WriteOnly Property Rotation() As Quat4f
            Set(ByVal value As Quat4f)
                Dim n, s As Single
                Dim xs, ys, zs As Single
                Dim wx, wy, wz As Single
                Dim xx, xy, xz As Single
                Dim yy, yz, zz As Single

                M = New Single(3, 3) {}

                n = (value.x * value.x) + (value.y * value.y) + (value.z * value.z) + (value.w * value.w)
                s = If((n > 0.0f), 2.0f / n, 0.0f)

                xs = value.x * s
                ys = value.y * s
                zs = value.z * s
                wx = value.w * xs
                wy = value.w * ys
                wz = value.w * zs
                xx = value.x * xs
                xy = value.x * ys
                xz = value.x * zs
                yy = value.y * ys
                yz = value.y * zs
                zz = value.z * zs

                ' rotation
                M(0, 0) = 1.0f - (yy + zz)
                M(0, 1) = xy - wz
                M(0, 2) = xz + wy

                M(1, 0) = xy + wz
                M(1, 1) = 1.0f - (xx + zz)
                M(1, 2) = yz - wx

                M(2, 0) = xz - wy
                M(2, 1) = yz + wx
                M(2, 2) = 1.0f - (xx + yy)

                M(3, 3) = 1.0f

                ' translation (pan)
                M(0, 3) = pan_Renamed.x
                M(1, 3) = pan_Renamed.y

                ' scale (zoom)
                For i As Integer = 0 To 2
                    For j As Integer = 0 To 2
                        M(i, j) *= scl
                    Next j
                Next i
            End Set
        End Property

Edit:

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

  1. Модель прыгает в другое место. Я хотел бы сохранить модель в том же месте и ориентации.

  2. Модель масштабируется относительно новой центральной точки, но мне бы хотелось, чтобы модель масштабировалась около точки, которая является средней величиной, по которой пользователь касается двумя пальцами.

Что касается номера 2, я думаю, что знаю, как это сделать, но мне нужно выяснить номер 1, чтобы номер 2 работал правильно. Для числа 2 я могу просто спроецировать среднюю точку касания на плоскость, которая параллельна ближней плоскости, но проходит через начало детали, а затем сделать это моим центром вращения, пока пользователь не поднимает пальцы вверх. Есть идеи по номеру 1? Код, который я использую для изменения центра вращения, приведен ниже:

glTranslatef(panVector.x, panVector.y, 0); //panVector is a variable that keeps track of the user panning the model
glMultMatrixf(arcballMatrix); //arcball matrix is the 16 element rotation/scale matrix that controls the model orientation
glTranslatef(-centerOfRotation.x, -centerOfRotation.y, -centerOfRotation.z); //centerOfRotation is a point that is set where I want the center of rotation to be

Только для вашей информации, OpenGL применяет матричные преобразования в обратном порядке из-за того, как работают его стеки. Так что в моем коде нижняя строка будет выполняться сначала, а затем вверх оттуда. Эффективно он перемещает модель так, чтобы ее центр вращения находился в начале координат, затем он вращается / масштабируется, а затем переводит модель туда, куда он должен пойти для панорамирования.

Проблема, с которой я столкнулся, заключается в том, что мне нужно добавить centerOfRotation обратно, когда я выполняю панорамирование, но проблема в том, что после поворота модели точку centerOfRotation нужно каким-то образом преобразовать, чтобы она оказалась в другой модели. пространство. До того как я повернул модель, она работает нормально, но как только вращение введено, все взрывается.

Ответы [ 2 ]

0 голосов
/ 01 февраля 2011

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

glTranslatef(panVector.x, panVector.y, 0); //panVector is a variable that keeps track of the user panning the model
glMultMatrixf(arcballMatrix); //arcball matrix is the 16 element rotation/scale matrix that controls the model orientation
glTranslatef(-centerOfRotation.x, -centerOfRotation.y, -centerOfRotation.z); //centerOfRotation is a point that is set where I want the center of rotation to be
0 голосов
/ 29 декабря 2010

Вместо того, чтобы портировать через arcball VB.NET, возможно, вы могли бы взглянуть на существующую реализацию трекбола iPhone. Например, Билл Дадни некоторое время назад написал пример приложения , в котором используется трекбол для вращения двух изображений в контексте Core Animation, что легко можно изменить для работы в OpenGL ES (использование Core Animation и OpenGL ES). идентичные матричные структуры для преобразований).

Я реализовал альтернативный способ поворота модели, используя сенсорное движение по осям X и Y для поворота вокруг осей Y и X экрана, видимого пользователем. Это можно найти в исходном коде моего Molecules приложения, а также в образце приложения , которое я написал и которое отображает трехмерный куб. Я немного объясню, как это работает здесь .

Оба эти подхода по-прежнему способны поворачивать модель относительно ее происхождения, даже если она смещена в определенном направлении.

...