Шаг 0: Получить gluUnproject:
Сообщения о том, что он нужен, верны.Эта функция делает всю тяжелую работу за вас.Я знаю, что в какой-то момент в проекте MESA была реализация, которая работала на iOS практически без изменений.Я не уверен, что это все еще доступно.За исключением этого, вам просто нужно будет провести какое-то исследование и либо свернуть свое собственное дело, либо перенести чье-то другое.Это немного тяжело для линейной алгебры, так что удачи.
Шаг 1: Конвертировать из координат UIKit в координаты OpenGL:
Обычно это включает в себя две вещи:
Переверните Y-координату, потому что UIKit любит свое происхождение в верхнем левом углу, тогда как OpenGL любит свое происхождение в левом нижнем углу.
touchLocation.y = [[self view] bounds].size.height - touchLocation.y;
Преобразование из «Единицы экрана» в пиксели.Это сохраняет согласованность между стандартными и сетевыми дисплеями.
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));