Управляйте вращением трехмерного объекта с помощью сенсорного экрана в openGL - PullRequest
3 голосов
/ 26 января 2011

Я учусь на 4-ом курсе компьютерного инжиниринга и имею некоторый опыт работы с Android-разработчиком.

Я работаю над приложением, в котором есть 3D-компонент, который требует от меня возможности его вращения.Я смотрел на пример на сайте ресурсов Android.

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.html

В этом примере не говорится о вращении вокруг оси z.Я уже пытался использовать Quaternion для поворотов, но я не понимаю, как получить повороты вокруг оси Z.

После того, как вы повернули что-то, оси больше не совпадают (x, y), так какМожете ли вы узнать, сколько вращаться, по какой оси?

Мне было интересно, если кто-нибудь может помочь мне узнать, как просто иметь возможность вращаться вокруг объекта.как в примере выше, но также вокруг оси Z.Я уже потратил около 24 часов на поиски и попытки выяснить это.

Большая проблема в том, что как только вы повернете на 90 градусов вокруг оси Y, как вы сможете обнаружить следующее вращение (движение вертикально на сенсорном экране?) должно быть вокруг оси Z.

Заранее спасибо.

Ответы [ 4 ]

1 голос
/ 13 января 2012

Добавьте xAngle и yAngle к текущей матрице.

Matrix.rotateM(matrix, 0, xAngleADD, matrix[1], matrix[5], matrix[9]);
Matrix.rotateM(matrix, 0, yAngleADD, matrix[0], matrix[4], matrix[8]);
gl.glMultMatrixf(matrix, 0);
0 голосов
/ 26 января 2011

Вы также можете вращать камеру вокруг центра вместо вращения объекта.

0 голосов
/ 27 января 2011

Ваш вопрос не совсем правильный.Не спрашивайте: «Как только вы вращаете что-то, оси больше не совпадают (x, y), так как вы можете узнать, сколько вращать по какой оси?», Спрашивайте «Как я могу вращаться вокруг глобальных осей, а не локально?оси?».Вы хотите, чтобы вращение вокруг вашего глобального x всегда было вращением вокруг глобального x, а не вращением вокруг локальной оси x вашего объекта.Вы не вращаетесь по-разному в соответствии с текущим состоянием, вы просто меняете то, что вращается вокруг себя.

Прежде всего, вы, вероятно, сохраняете, скажем, RotX, RotY и RotZ и вызываете glRotatef для применения.вращение?Этого недостаточно для того, что вы хотите сделать.То, что вы делаете, описываете ориентацию по углам Эйлера.Вы всегда будете сталкиваться с карданным замком , в котором некоторые значения для одной из осей превращают две другие оси в одну и ту же ось.Таким образом, вы теряете степень свободы.Прочтите статью для правильного объяснения.

Поскольку вы будете очень довольны ими как кодировщиком OpenGL, предположим, что вместо этого вы сохраняете ориентацию объекта непосредственно как матрицу с именем M. Вы сохраняете вращение как матрицуВы применяете для достижения вращения.Там нет явного понятия углов или осей.

Предположим, вы хотите вращаться вокруг х.Вы генерируете подходящую матрицу вращения вокруг оси x, назовите ее R. Такая матрица была бы той, которую OpenGL построил бы для внутреннего выполнения glRotatef (angle, 1, 0, 0).

Тогда у вас действительно естьдва варианта - заменить M на MR или заменить M на RM.Умножение матриц не является коммутативным, поэтому это не одно и то же.Точно так же, как использование стека матрицы OpenGL для преобразования шести влево, а затем поворота на 40 градусов, результат, отличный от поворота на 40 градусов и последующего преобразования шести влево.

В этом случае R является объектом,таким образом, MR - это постмножение, а RM - предварительное умножение.Умножение матриц создает матрицу, которая при применении к вектору имеет тот же эффект, что и вторая, а затем первая.Так что, если вы умножите результат, вы получите результат, как если бы вы повернули объект новым вращением, а затем все те, которые предшествовали ему.Это, очевидно, неправильно.Вы хотите, чтобы новая модификация вступила в силу после всех других изменений на сегодняшний день.Таким образом, вы умножаете.А затем сохраните результат как новый M.

Это все, что нужно, на самом деле.Вы можете получить быстрое подтверждение концепции, явно используя стек матрицы GL, например:

// ... I assume the modelview stack is active, M is an array of 16 floats ...

// ensure whatever's on the stack currently is kept safe
glPushMatrix();

    // but we don't actually care what it was, so load the identity
    glLoadIdentity();

    // build our rotation matrix first
    glRotatef(changeAroundX, 1, 0, 0);
    glRotatef(changeAroundY, 0, 1, 0);

    // multiply by M. OpenGL postmultiplies by the newer matrix, so this
    // is premultiplying M by whatever we just loaded
    glMultMatrixf(M);

    // read the new M back
    glGetFloatv(GL_MODELVIEW_MATRIX, M);

// and pretend we never touched the stack
glPopMatrix();

Затем используйте glMultMatrixf (M) вместо glRotatef, чтобы применить текущее вращение объекта.Это всего лишь подтверждение концепции, потому что вы быстро получите некоторые неприятные числовые ошибки в M, просто из-за большого количества манипуляций с ним.Вы можете исправить M по мере продвижения, но если у вас уже есть кватернионный код и вы им довольны, возможно, будет разумнее пойти по этому пути.Просто замените операции логической матрицы кватернионными эквивалентами.

0 голосов
/ 26 января 2011

Я рекомендую вам прочитать эту книгу ссылка

Конкретно ваш вопрос: см. Часть 3.3.1

...