(iPhone) Я пытаюсь сделать так, чтобы пользователь мог вращать объект, проводя пальцем по экрану. Перетаскивание влево или вправо должно вращаться вокруг оси Y, а перетаскивание вверх или вниз должно вращаться вокруг оси X. Вот мой исходный код:
glRotatef( yAmt, 0, 1, 0 );
glRotatef( xAmt, 1, 0, 0 );
Вращение все сумасшедшее и, кажется, идет в случайных направлениях. Я почти уверен, что это связано с тем, что второе утверждение зависит от первого утверждения, но я пытался отрицать это с помощью какой-то причудливой математики и все еще не мог сделать это правильно.
Что ж, я частично разобрался, но теперь у меня новая проблема (как сложить два вращения?).
МОЕ РЕШЕНИЕ:
Допустим, вы хотите повернуть куб влево на 90, а затем вниз на 90. Попробуйте сделать так:
glRotatef( 90, 0, 1, 0 );
glRotatef( 90, 1, 0, 0 );
Это не работает. Вторая функция ведет себя странно, потому что первая функция поменяла местами оси X и Z. Итак, вы попробуйте это:
glRotatef( 90, 0, 1, 0 );
glRotatef( 90, 0, 0, 1 );
Теперь у вас есть желаемый результат, но если вы измените величину поворота по оси Y в первой функции на 180, 45 или что-то еще, снова произойдет сбой. Желаемый вектор поворота зависит от величины поворота Y от первой функции. Желаемый результат достигается при этом:
glRotatef( yAmt, 0, 1, 0 );
glRotatef( xAmnt, cos(yAmt), 0, sin(yAmt) );
А что, если вы хотите сначала повернуть вверх и вниз, а затем слева направо? Это последнее решение не работает, потому что, во-первых, функции расположены в неправильном порядке, а во-вторых, ось Y также зависит от поворота по оси X. Вы должны учитывать это, И вы должны объединить две функции, в результате чего:
glRotatef( totalAmt, xFactor*cos(yAmt), yFactor*cos(xAmt), xFactor*sin(yAmt) + yFactor*sin(xAmt) );
Где xFactor и yFactor складываются в желаемый вектор вращения (1,0 для вверх и вниз, 0,1 для левого и правого, sqrt(.5), sqrt(.5) для диагонального вращения).
МОЯ ПРОБЛЕМА:
Проблема возникает, когда пользователь заканчивает одно вращение и начинает новое. Вы должны помнить и «воспроизводить» предыдущее вращение, иначе вы получите нежелательный «скачок» обратно к 0 вращению. Один новый поворот — это нормально, я могу реализовать touchesEnded, чтобы запомнить параметры glRotatef, а затем подключить их к новому повороту следующим образом:
glRotatef( amt_old, x_old, y_old, z_old );
glRotatef( totalAmt, xFactor*cos(yAmt), yFactor*cos(xAmt), xFactor*sin(yAmt) + yFactor*sin(xAmt) );
Но во втором новом вращении у меня теперь есть два вращения, чтобы «переиграть». Я не могу понять, какие значения присвоить amt_old, x_old, y_old и z_old. К чему это сводится, так это... как суммировать два вращения glRotatef?