OpenGL GL_SELECT или ручное обнаружение столкновений?

Как видно на изображении

http://oi56.tinypic.com/ifu33k.jpg

Я рисую множество контуров (полигонов) как GL_LINE_STRIP. Теперь я хочу выбрать кривую (многоугольник) под мышью, чтобы удалить, переместить.. и т. Д. В 3D .

Мне интересно, какой метод использовать:

1. использовать сборку и выбор OpenGL. (glRenderMode (GL_SELECT))

2. Используйте ручное обнаружение столкновений, используя пик-луч и проверьте, находится ли луч внутри каждого многоугольника.

7 ответов

Решение

Я настоятельно рекомендую против GL_SELECT. Этот метод очень старый и отсутствует в новых версиях GL, и вы, скорее всего, получите проблемы с современными видеокартами. Не ожидайте, что он будет поддерживаться аппаратными средствами - возможно, вы встретите программный (драйвер) запасной вариант для этого режима на многих графических процессорах, если он будет работать вообще. Используйте на свой риск:)

Позвольте мне предоставить вам альтернативу.

Для твердых, больших объектов, есть старый, хороший подход выбора:

  • включение и настройка теста ножниц в окне 1x1 в позиции курсора
  • рисование экрана без освещения, текстурирования и мультисэмплинга, назначение уникального сплошного цвета для каждого "важного" объекта - этот цвет станет идентификатором объекта для выбора
  • вызов glReadPixels и получение цвета, который затем будет использоваться для идентификации выбранного объекта
  • очистка буферов, сброс ножниц до нормального размера и нормальное рисование сцены.

Это дает вам очень надежный метод выбора для каждого объекта. Кроме того, отрисовка и очистка только 1 пикселя с минимальной обработкой на пиксель не сильно скажется на вашей производительности, если только у вас недостаточно вычислительной мощности вершин (я думаю, это маловероятно) или у вас действительно много объектов и вы, вероятно, получите процессор- ограничено числом вызовов отрисовки (но, опять же, я считаю, что можно оптимизировать это до одного вызова отрисовки, если бы вы могли передать цвет в виде данных на пиксель).

Цвет в RGB составляет 3 байта без знака, но должна быть возможность дополнительно использовать альфа-канал кадрового буфера для последнего байта, так что вы получите всего 4 байта - достаточно для хранения любого 32-битного указателя на объект как цвет.

Кроме того, вы можете создать выделенный объект кадрового буфера с определенным форматом пикселей (например, GL_R32UI, или даже GL_RG32UI если вам нужно 64 бита) для этого.

Вышесказанное является хорошей и быстрой альтернативой (как с точки зрения надежности, так и времени реализации) для строгого геометрического подхода.

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

Первым было провести тест столкновения процессора, который работал, но не так быстро, как мне бы хотелось. Это определенно замедляется, когда вы отбрасываете лучи на экран (используя gluUnproject), а затем пытаетесь найти объект, с которым сталкивается мышь. Единственный способ получить удовлетворительные скорости - это использовать октодерево, чтобы уменьшить количество тестов на столкновение, а затем выполнить тест на столкновение с ограничивающей рамкой - однако это привело к методу, который не был идеальным по пикселям.

Метод, на котором я остановился, состоял в том, чтобы сначала найти все объекты под мышью (используя gluUnproject и тесты столкновений ограничивающего прямоугольника), что обычно очень быстро. Затем я визуализировал каждый из объектов, которые потенциально сталкивались с мышью в буферном буфере, другим цветом. Затем я использовал glReadPixel, чтобы получить цвет под мышью и отобразить его обратно на объект. glReadPixel - медленный вызов, так как он должен читать из буфера кадра. Тем не менее, это делается один раз за кадр, что в конечном итоге занимает незначительное количество времени. Вы можете ускорить его, рендеринг в PBO, если хотите.

Giawa

Уманга, не могу посмотреть, как ответить inline... может быть, я должен зарегистрироваться:)

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

Получите положение камеры к вектору мыши, как сказано выше

Для каждого контура обведите все координаты попарно (0-1, 1-2, 2-3, ... n-0) в нем и сделайте из них вектор, как и раньше. Т.е. ходить по контуру.

Теперь сделайте перекрестное продвижение этих двух (от контура до мыши), а не между парами, как я говорил ранее, сделайте это для всех пар и векторов сложите их все.

В конце найдите величину результирующего вектора. Если результат равен нулю (с учетом ошибок округления), то вы вне фигуры - независимо от облицовки. Если вы заинтересованы в обращении к лицу, то вместо магнита вы можете сделать эту точку с помощью вектора мыши, чтобы найти лицо и проверить знак +/-.

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

См. Http://en.wikipedia.org/wiki/Gauss%27s_law и отметьте, что "правая часть уравнения - это суммарный заряд, заключенный в S, деленный на электрическую постоянную" с пометкой "заключено" - т.е. ноль значит не вложено.

Вы все еще можете сделать эту оптимизацию с помощью ограничителей для скорости.

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

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

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

Возьмите первую координату первого контура и сделайте вектор для второй координаты. Сделайте из них вектор. Возьмите 3-ю координату и сделайте вектор от 2 до 3, повторите все вокруг вашего контура и, наконец, сделайте последний из координат n обратно в 0 снова. Для каждой пары в последовательности найдите перекрестное произведение и суммируйте все результаты. Когда у вас есть этот окончательный вектор суммирования, держите его и делайте точечное произведение с вектором направления указателя мыши. Если его + ve, то мышь находится внутри контура, если -ve, то его нет, а если 0, то я предполагаю, что плоскость контура и направление мыши параллельны.

Сделайте это для каждого контура, и тогда вы будете знать, какие из них пронзены вашей мышью. Вам решать, какой вы хотите выбрать из этого набора. Самый высокий Z?

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

В прошлом я использовал GL_SELECT, чтобы определить, какой объект (ы) предоставил интересующий пиксель (пиксели), а затем использовал вычислительную геометрию, чтобы получить точное пересечение с объектом (ами), если требуется.

Вы ожидаете выбрать, щелкнув контур (на краю) или внутренность многоугольника? Ваш второй подход звучит так, как будто вы хотите, чтобы щелчки в интерьере выбирали самый плотный, содержащий многоугольник. Я не думаю что GL_SELECT после рендеринга GL_LINE_STRIP собирается сделать интерьер реагирующим на щелчки.

Если бы это был настоящий контурный график (по изображению, которое я не думаю, ребра пересекаются), то был бы доступен гораздо более простой алгоритм.

Первый прост в реализации и широко используется.

Другие вопросы по тегам