пятница, 11 ноября 2011 г.

Выбор объектов в OpenGL

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

 

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

    FloatBuffer fb=FloatBuffer.allocate(1);

    gl.glReadPixels(x,h-y-1, 1, 1, GL2.GL_DEPTH_COMPONENT, GL.GL_FLOAT, fb);

получаем z координату пикселя под мышью - это z координата самого верхнего из попавших под мышь объектов. А все объекты мы предварительно разнесли по z-координате и создали карту z -> объект. Вот и все - достаем из карты объект и радуемся.

 

А вот и не все... Вокруг каждого объекта есть квадратная прозрачная область (мы берем текстуру и натягиваем ее на квадрат). И как выяснилось - прозрачная она лишь для меня, но не для glReadPixels. В результате мы попадаем в объект просто ткнув рядом. Хуже того - мы тыкаем в один объект, а попадаем в другой, который этой прозрачной областью его перекрывает. Однако решение этой проблемы тривиально до безобразия, и видимо из-за этого его хрен найдешь.

 

Ставим в начало программы:

     gl.glEnable(GL2.GL_ALPHA_TEST);

    gl.glAlphaFunc(GL2.GL_GREATER, 0.01f);

В результате пиксели со значением alpha<0.01 (а у нас ровно 0) в буфер не попадают и не портят нам малину. Теперь объект можно выбрать хоть через дырку в другом объекте.

Пришлось еще переставить обработку мышиных событий - теперь мышь обрабатывается после отрисовки.

А еще надо помнить, что машина может представить десятичное значение совсем не так как мы ожидаем (например 0.003999 вместо 0.004), так что формируя индекс нужно его аккуратненько округлить и не полагаться лишний раз на автоматическое приведение типов.

Ну и не стоит забывать что в буфере глубины у нас значение 0 : 1.0, а объекты мы рисуем в диапазоне -1.0 : 1.0, а то я все не мог понять, что за левые координаты получаются

float z=fb.get(0);

z=1 - (z*2);

З.Ы. Завтра буду учить свои кораблики стрелять

Комментариев нет:

Отправить комментарий