2010-12-28 3 views
0

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

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

ответ

0

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

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

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

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

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

+0

Я рассматривал эту проблему со всех сторон, и я действительно хотел бы придерживаться метода, который я использую, поскольку я верю он дает лучший пользовательский интерфейс и является самым настраиваемым с точки зрения того, как он себя ведет. Похоже, что это должно быть довольно прямолинейно, чтобы сделать это только повернуть модель о происхождении. Я также хотел бы установить, где «происхождение», чтобы вращаться, находится в координатах X, Y, Z. – Davido

Смежные вопросы