Как определить, что касается экрана в 3D-пространстве? - PullRequest
6 голосов
/ 21 марта 2010

Как использовать gl.gluUnproject в моем приложении OpenGL ES 1.1 для Android, чтобы определить, что выбирается, когда пользователь касается экрана?

Насколько я понимаю, событие касания приводит к линии, и я должен найти первую «вещь», с которой оно пересекается.

Есть ли какие-нибудь учебники о том, как это сделать?

Ответы [ 4 ]

4 голосов
/ 21 марта 2010

Если вы выбираете 2D в 3D, вам нужно немного поиграть с матрицами и векторами.GlUnproject не существует для OpenGL ES 1.1, поэтому вы должны сделать некоторые математические самостоятельно.

Пересечение луча с объектом - это путь.Ответ Timmmms уже охватывает некоторые из них, но это еще не все.Идея состоит в том, чтобы создать луч в 3D из 2D координат.Для этого необходимы обратная матрица и матрица проекции.Когда у вас есть луч, вы можете использовать тест пересечения лучей по вашему выбору, и, конечно, вам нужно выбрать ближайший объект, как в пункте 4 Тиммма. Простые в использовании ограничивающие сферы и ограничивающие рамки, а в Интернете полно учебников по проверке пересечений.

Это руководство по комплектации предназначено для DirectX, но вы можете понять эту идею.Часть построения луча является наиболее важной.

Редактировать Android реализует свою собственную версию gluUnproject.Его можно использовать для создания луча, вызывая его для ближней и дальней плоскости (0 и 1) и вычитая результаты ближней плоскости из результатов дальней плоскости, чтобы получить направление луча.Происхождение луча - это место просмотра.Подробнее здесь .

2 голосов
/ 21 марта 2010

Я думаю, что для большинства приложений вы должны выбрать правильный 3D-подход: приведение лучей.

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

Учитывая точность ручных устройств, это уже должно быть достаточной точностью.Обратите внимание, что в зависимости от формы объекта вам может понадобиться более одного базового примитива.Кроме того, бессмысленно всегда использовать один и тот же примитив: очевидно, что ограничивающая сфера - очень плохое приближение для очень длинного стержня.

1 голос
/ 22 марта 2010

Одна мысль у меня была кешировать результаты вызова gluProject. Это может быть практичным, когда вы имеете дело с фиксированной камерой. В конце любого изменения перспективы камеры я могу восстановить этот кэш «touchables».

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

Буду признателен за любые мысли об этом подходе!

1 голос
/ 21 марта 2010

Это полностью зависит от того, что вы делаете. Вы, вероятно, не должны использовать подход выбора, потому что

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

Как я уже сказал, это полностью зависит от вашей игры. Если это 2D или почти 2D игра, тогда все просто, и вы просто вводите сенсорные координаты в свою игровую модель. Для 3D-игр я бы предложил этот простой алгоритм, который я только что придумал:

  1. Составьте список всех сенсорных игровых объектов, которые могли быть затронуты.
  2. Преобразуйте их координаты центра в трехмерные координаты экрана. (2D экранные координаты описаны здесь: http://www.flipcode.com/archives/Plotting_A_3D_Point_On_A_2D_Screen.shtml)
  3. Найдите двухмерное расстояние до каждого объекта, отбросьте объекты с расстоянием, превышающим ваш порог касания.
  4. Найти ближайший объект по некоторой метрике расстояния. Вам придется экспериментировать на этом этапе, и снова, это зависит от характера игры.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...