Узким местом является цикл for и последовательность glBegin
/glEnd
. Данные считываются из файлов в каждом кадре. Обратите внимание, что рисование с использованием glBegin
/glEnd
последовательности, а матричный стек с фиксированной функцией устарел десятилетиями. Прочитайте файлы один раз при запуске и создайте объект Vertex Buffer. (Подробнее о спецификации вершин и Shader для современного способа рендеринга.)
Ближайшим решением для вашего существующего кода является использование возможности на стороне клиента glEnableClientState
и фиксированные атрибуты функций glVertexPointer
< /а>. С этим решением вам не нужна никакая шейдерная программа.
Далее я предполагаю, что вы используете PyOpenGL.
Загрузите координаты вершины в массив
def LoadVertices(pcd_files):
vertices = []
for i in pcd_files:
pc = pypcd.PointCloud.from_path(i)
number_of_points = pc.get_metadata().get('points')
z = pc.pc_data['z']
x = pc.pc_data['x']
y = pc.pc_data['y']
for j in range(number_of_points):
vertices += [x[j], y[j], z[j]]
return vertices
Создайте объект Vertex Buffer и создайте и инициализируйте хранилище данных буферного объекта:
import ctypes
def CreateBuffer(vertices):
bufferdata = (ctypes.c_float*len(vertices))(*vertices) # float buffer
buffersize = len(vertices)*4 # buffer size in bytes
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, buffersize, bufferdata, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0)
return vbo
Создайте функцию, которая может рисовать примитивы Point из буфера:
def DrawBuffer(vbo, noOfVertices):
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, 0, None)
glDrawArrays(GL_POINTS, 0, noOfVertices)
glDisableClientState(GL_VERTEX_ARRAY)
glBindBuffer(GL_ARRAY_BUFFER, 0)
Используйте эти функции в своей программе:
files = glob.glob(os.getcwd() + "\\" + PCD_OutPutDirectory + "\*.pcd")
pygame.init()
display = (1700, 1000)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
vArray = LoadVertices(files)
noPoints = len(vArray) // 3
bufferObj = CreateBuffer(vArray)
gluPerspective(50, (display[0] / display[1]), 0.1, 5000)
glTranslatef(0, 0, -1000)
Clock = pygame.time.Clock()
while True:
Clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef(2, 1, 1, 3)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
DrawBuffer(bufferObj, noPoints)
pygame.display.flip()
Если вы хотите добавить отдельные цвета для каждой точки, то вершина и ее атрибут должны состоять не только из координат (x, y, z)
, но и должны иметь Цвет RGB (x, y, z, r, g, b)
, поэтому каждый кортеж атрибута состоит из 6 компонентов, а не из 3.
Атрибут цвета фиксированной функции должен быть включен состоянием клиента GL_COLOR_ARRAY
. Добавьте атрибут, указанный в glColorPointer
.
Каждый кортеж атрибута имеет размер 24 байта, потому что кортеж состоит из 6 компонентов (x, y, z, r, g, b)
и каждый компонент имеет размер 4 байта (это размер float
).
Этот размер должен быть передан в 3-й параметр (sride
) из glVertexPointer
соответственно glColorPointer
.
Если именованный объект буфера связан, то последний параметр glVertexPointer
соответственно glColorPointer
обрабатывается как смещение в байтах в хранилище буфера объектов буфера. Смещение — это количество байтов до 1-го компонента атрибута.
В случае glVertexPointer
смещение равно 0, поскольку (x, y, z)
— это первые компоненты в кортеже атрибута. В случае glColorPointer
смещение составляет 3 * 4 = 12 байт, потому что (r, g, b)
находятся после 3 координат (x, y, z)
, а размер каждого компонента равен 4. Поскольку тип последнего параметра является указателем, смещение должно быть приведено к ctypes.c_void_p
(например, ctypes.c_void_p(3*4)
). Для этой встроенной библиотеки python должен быть импортирован. Если смещение равно 0, вместо ctypes.c_void_p(0)
можно использовать None
.
Спецификация атрибутов вершины может выглядеть следующим образом:
glBindBuffer(GL_ARRAY_BUFFER, vbo)
stride = 6*4 # (24 bates) : [x, y, z, r, g, b] * sizeof(float)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, stride, None)
glEnableClientState(GL_COLOR_ARRAY)
offset = 3*4 # (12 bytes) : the rgb color starts after the 3 coordinates x, y, z
glColorPointer(3, GL_FLOAT, stride, ctypes.c_void_p(offset))
Все вместе:
import ctypes
def LoadVertices(pcd_files):
attributes = []
for i in pcd_files:
pc = pypcd.PointCloud.from_path(i)
number_of_points = pc.get_metadata().get('points')
z = pc.pc_data['z']
x = pc.pc_data['x']
y = pc.pc_data['y']
r = # set the RGB color data here
g =
b =
for j in range(number_of_points):
attributes += [x[j], y[j], z[j], r[j], g[j], b[j]]
return attributes
def CreateBuffer(attributes):
bufferdata = (ctypes.c_float*len(attributes))(*attributes) # float buffer
buffersize = len(attributes)*4 # buffer size in bytes
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, buffersize, bufferdata, GL_STATIC_DRAW)
glBindBuffer(GL_ARRAY_BUFFER, 0)
return vbo
def DrawBuffer(vbo, noOfVertices):
glBindBuffer(GL_ARRAY_BUFFER, vbo)
stride = 6*4 # (24 bates) : [x, y, z, r, g, b] * sizeof(float)
glEnableClientState(GL_VERTEX_ARRAY)
glVertexPointer(3, GL_FLOAT, stride, None)
glEnableClientState(GL_COLOR_ARRAY)
offset = 3*4 # (12 bytes) : the rgb color starts after the 3 coordinates x, y, z
glColorPointer(3, GL_FLOAT, stride, ctypes.c_void_p(offset))
glDrawArrays(GL_POINTS, 0, noOfVertices)
glDisableClientState(GL_VERTEX_ARRAY)
glDisableClientState(GL_COLOR_ARRAY)
glBindBuffer(GL_ARRAY_BUFFER, 0)
files = glob.glob(os.getcwd() + "\\" + PCD_OutPutDirectory + "\*.pcd")
pygame.init()
display = (800, 600)
pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
vArray = LoadVertices(files)
noPoints = len(vArray) // 6 # 6 components per attribute tuple
bufferObj = CreateBuffer(vArray)
gluPerspective(50, (display[0] / display[1]), 0.1, 5000)
glTranslatef(0, 0, -1000)
Clock = pygame.time.Clock()
while True:
Clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glRotatef(2, 1, 1, 3)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
DrawBuffer(bufferObj, noPoints)
pygame.display.flip()
27.06.2019