Как я определяю то, что затронуто в 3D пространстве с экрана?

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

Мое понимание - то, что сенсорное событие приводит к строке, и я должен найти первую "вещь", с которой оно пересекается.

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

6
задан Alexander Trauzzi 21 March 2010 в 16:05
поделиться

4 ответа

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

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

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

1
ответ дан 16 December 2019 в 21:37
поделиться

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

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

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

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

4
ответ дан 16 December 2019 в 21:37
поделиться

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

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

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

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

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

1
ответ дан 16 December 2019 в 21:37
поделиться

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

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

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

2
ответ дан 16 December 2019 в 21:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: