Рисование вогнутого многоугольника в OpenGL

У меня есть вогнутый многоугольник, который мне нужно нарисовать в OpenGL.
Многоугольник определяется как список точек, которые формируют его внешнее кольцо, и список списков точек, которые определяют его внутренние кольца (зоны исключения).

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

Решение с Boost.Geometry будет хорошим, так как я уже интенсивно использую его в своем приложении.

Мне это нужно для работы на iPhone, а именно OpenGL ES (более старая версия с фиксированным конвейером).

Как я могу это сделать?

4 ответа

Решение

Попробуйте возможности тесселяции OpenGL. Вы можете использовать его для преобразования сложного многоугольника в набор треугольников, которые вы можете визуализировать напрямую.

РЕДАКТИРОВАТЬ (в ответ на комментарий): OpenGL ES не поддерживает функции тесселяции. В этом случае, и если полигон представляет собой статические данные, вы можете создать тесселяцию в автономном режиме с помощью OpenGL на своем настольном компьютере или ноутбуке.

Если форма динамическая, то вам не повезло с OpenGL ES. Однако существует множество библиотек (например, CGAL), которые будут выполнять ту же функцию.

Это немного сложный и дорогостоящий метод, но любой вогнутый многоугольник можно нарисовать с помощью следующих шагов (обратите внимание, что этот метод работает точно на плоских многоугольниках, но я также предполагаю, что вы пытаетесь рисовать на плоской поверхности или в 2D-ортогональном режиме):

  • включить проверку трафарета, использовать glStencilFunc(GL_ALWAYS,1,0xFFFF)
  • отключить маску цвета, чтобы предотвратить нежелательные отрисовки: glColorMask(0,0,0,0)
  • Я думаю, что у вас есть вершины в массиве типа double или в другой форме (настоятельно рекомендуется, так как этот метод рисует один и тот же многоугольник несколько раз, но можно использовать glList или glBegin-glEnd)
  • задавать glStencilOp(GL_KEEP,GL_KEEP,GL_INCR)
  • нарисовать многоугольник как GL_TRIANGLE_FAN

Теперь на слое трафарета у вас есть биты, установленные>0, где были нарисованы треугольники многоугольника. Хитрость заключается в том, что вся действительная область многоугольника заполнена значениями, имеющими mod2=1, это потому, что рисунок веерного треугольника перемещается вдоль поверхности многоугольника, и если выбранный треугольник имеет площадь за пределами многоугольника, он будет нарисован дважды (один раз в текущая последовательность, затем на следующих чертежах, когда нарисованы действительные области) Это может происходить много раз, но во всех случаях пиксели вне многоугольника рисуются четные времена, пиксели внутри рисуются нечетные времена. Могут возникнуть некоторые исключения, когда порядок пикселей приводит к тому, что внешние области больше не рисуются. Чтобы отфильтровать эти случаи, необходимо нарисовать массив вершин в обратном направлении (все эти случаи работают правильно при переключении порядка): - установите glStencilFunc(GL.GL_EQUAL,1,1), чтобы эти ошибки не происходили в обратном направлении (можно рисовать только области внутри многоугольника, нарисованного в первый раз, поэтому ошибки, возникающие в другом направлении, не будут возникать, логически это создает пересечение двух половин решения) - рисовать многоугольник в обратном порядке, сохраняя glStencilFunc для увеличения значений развернутых пикселей. Теперь у нас есть правильный слой трафарета с pixel_value%2=1, где пиксель действительно находится внутри многоугольника. Последний шаг - нарисовать сам многоугольник: - установить glColorMask(1,1,1,1) чтобы нарисовать видимый многоугольник - оставьте glStencilFunc(GL_EQUAL,1,1), чтобы нарисовать правильные пиксели - рисуйте многоугольник в том же режиме (массивы вершин и т. д.), или если вы рисуете без освещения / текстурирования, один прямоугольник всего экрана может также рисовать (быстрее, чем рисовать все вершины, и будут установлены только правильные пиксели многоугольника)

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

Проверьте клеи, которые имеют функции тесселяции, которые могут обрабатывать вогнутые многоугольники.

Я написал класс java для небольшой графической библиотеки, которая делает именно то, что вы ищете, вы можете проверить это здесь:

https://github.com/DzzD/TiGL/blob/main/android/src/fr/dzzd/tigl/PolygonTriangulate.java

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

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

Как это :

Чтобы лучше понять увеличение, это будет выглядеть так:

Наконец, это всего лишь один полигон.

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