2-мерный glRotatef () - PullRequest
       19

2-мерный glRotatef ()

1 голос
/ 12 апреля 2011

(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?

Ответы [ 2 ]

0 голосов
/ 14 июня 2011

Получил ответ от пользователя на другом форуме:

// init the matrix

... просмотр метода init

theCurrentMatrix = CATransform3DIdentity;

...

// вычисление поворота, когда пользовательский сенсорный экран:

- (void) rotateX:(float)inX Y:(float)inY
{
     GLfloat lAngle=sqrt(inX*inX+inY*inY);

 if (lAngle != 0.0f)
 {
      static const float _degToRad = M_PI / 180.0;
            // we compute a rotation matrix (in radians)
      CATransform3D lRotation = CATransform3DMakeRotation(lAngle * _degToRad, inX, inY, 0.0f);

            // apply the rotation to the current matrix (cumulative effect)
            // order is important
      theCurrentMatrix = CATransform3DConcat(theCurrentMatrix, lRotation);
 }

}

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
     // Get touch
     UITouch *touch = [[touches allObjects] objectAtIndex:0];

     if ([touches count] == 1)
     {
          UITouch *touch = [[touches allObjects] objectAtIndex:0];
          CGPoint location = [touch locationInView:touch.view];
      CGPoint previousLocation = [touch previousLocationInView:touch.view];

      CGFloat lDeltaX = (location.x - previousLocation.x)*1.0;
      CGFloat lDeltaY = (location.y - previousLocation.y)*1.0;

      // rotate the current matrix
      [self rotateX:lDeltaYY:lDeltaX];
 }

}

// Применение поворота (ей) ...

glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();


 glTranslatef(0.0f,0.0f,-100.0f);   // move a little to see the object


 glMultMatrixf(theCurrenMatrixPtr]);

... нарисуйте свои объекты

0 голосов
/ 12 апреля 2011

xAmt и yAmt в пикселях?Является ли вход для glRotatef в градусах ( EDIT: Я имел в виду радианы, конечно)?Если это так, умножьте на небольшое число;попробуйте (float)(M_PI/180) для одного пикселя на градус.

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


РЕДАКТИРОВАТЬ: Возможно, вам нужны glGetMatrix () и glLoadMatrix ().

...