Объединение нескольких отрезков - PullRequest
1 голос
/ 21 декабря 2009

Моя программа использует PyOpenGL (так что это Python) с psyco.

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

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

Любые идеи будут высоко оценены.

Ответы [ 3 ]

4 голосов
/ 21 декабря 2009

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

Не используйте GL_LINE_STRIPS, используйте один список GL_LINES, чтобы их можно было визуализировать за один раз.

Используйте glDrawArrays вместо немедленного рендеринга в режиме:

float* coordinates = {....}; //x and y coordinate pairs for all line segments
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(float), coordinates);
glDrawArrays(GL_LINES, 0, 2 * linecount);
glDisableClientState(GL_VERTEX_ARRAY);

(Для еще большей производительности вы можете хранить буфер вершин в чем-то, называемом объектом буфера вершин, но для начала все будет хорошо)

И последнее: если вы отбираете данные для каждой строки, вероятно, быстрее пропустить это и отправить все строки в графический процессор.

0 голосов
/ 21 декабря 2009

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

Одним из примеров является этот алгоритм:

  1. Построить новый отрезок X из двух точек, наиболее удаленных друг от друга в двух отрезках A и B.
  2. Найдите минимальное расстояние до X для всех точек в A и B.
  3. Назначьте ошибку как максимальное из этих минимальных расстояний.
  4. Замените A и B на X, если ошибка ниже вашего порога.

Это не лучший алгоритм, но его легко реализовать.

Редактировать 1

Обязательно попробуйте выполнить списки отображения или рендеринг объекта буфера вершин перед реализацией.

0 голосов
/ 21 декабря 2009

20K сегментов не так уж много. Кроме того, вам повезет, если вы сможете объединить 10-100 строк на кадр, поэтому ускорение этой оптимизации будет незначительным. Процесс рендеринга, вероятно, медленный, потому что вы создаете модель снова и снова. Используйте glNewList() для сохранения всех команд рендеринга в списке рендеринга GL на карте, а затем просто введите glCallList() для рендеринга одной командой.

...