Преобразование координат сенсорного экрана в трехмерные мировые координаты Opengl на iphone - PullRequest
3 голосов
/ 23 января 2012

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

Как преобразовать точку, возвращаемую от прикосновения к экрану, во что-то, что я могу использовать в мировых координатах GL?

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

Может кто-нибудь выложить это прямо для меня, пожалуйста?

Я использую Objective C, XCode и компилирую для iphone.

1 Ответ

3 голосов
/ 23 января 2012

Шаг 0: Получить gluUnproject:

Сообщения о том, что он нужен, верны.Эта функция делает всю тяжелую работу за вас.Я знаю, что в какой-то момент в проекте MESA была реализация, которая работала на iOS практически без изменений.Я не уверен, что это все еще доступно.За исключением этого, вам просто нужно будет провести какое-то исследование и либо свернуть свое собственное дело, либо перенести чье-то другое.Это немного тяжело для линейной алгебры, так что удачи.

Шаг 1: Конвертировать из координат UIKit в координаты OpenGL:

Обычно это включает в себя две вещи:

  1. Переверните Y-координату, потому что UIKit любит свое происхождение в верхнем левом углу, тогда как OpenGL любит свое происхождение в левом нижнем углу.

    touchLocation.y = [[self view] bounds].size.height - touchLocation.y;
    
  2. Преобразование из «Единицы экрана» в пиксели.Это сохраняет согласованность между стандартными и сетевыми дисплеями.

    CGFloat scale = [[UIScreen mainScreen] scale];
    touchLocation.y *= scale;
    touchLocation.y *= scale;
    

Шаг 3: Используйте gluUnproject для преобразованной координаты:

gluUnproject() технически преобразует 3D-точку в пространстве окна в 3D-точку в мировом пространстве.Итак, чтобы получить луч, вам нужно вызвать его дважды: один раз для ближней плоскости отсечения и один раз для дальней плоскости отсечения.Это даст вам две точки, из которых вы можете получить луч.Для вызова gluUnproject() вам потребуется доступ к координате вашего 2D-вида, текущему окну просмотра OpenGL, текущей матрице вида модели OpenGL и текущей матрице проекции OpenGL.Псевдокод:

Vector3 near, far;
gluUnProject(touchLocation.x, touchLocation.y, 0, _modelview, _projection, _viewport, &near.x, &near.y, &near.z);
gluUnProject(touchLocation.x, touchLocation.y, 1, _modelview, _projection, _viewport, &far.x, &far.y, &far.z);
return MakeRay(near, Vector3Subtract(far, near));
...