ボトルネックは for ループとglBegin
/glEnd
シーケンスです。データはフレームごとにファイルから読み取られます。glBegin
/glEnd
シーケンスと固定関数マトリックス スタックを使用した描画は、何十年も前から非推奨になっていることに注意してください。起動時にファイルを 1 回読み取り、Vertex Buffer Objectを作成します。(最先端のレンダリング方法については、Vertex Specificationと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
頂点バッファ オブジェクトを作成し、バッファ オブジェクトのデータ ストアを作成して初期化します。
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()
各ポイントに個別の色を追加したい場合、頂点とその属性は座標だけで構成されているだけでなく、 RGB カラー(x, y, z)
も必要であるため、各属性タプルは 3 つではなく 6 つのコンポーネントで構成されています。 (x, y, z, r, g, b)
固定機能の色属性は、クライアントの状態によって有効にする必要がありますGL_COLOR_ARRAY
。で指定された属性を追加しますglColorPointer
。
各属性タプルのサイズは 24 バイトです。これは、タプルが 6 つのコンポーネントで構成(x, y, z, r, g, b)
され、各コンポーネントのサイズが 4 バイトであるためです (これは のサイズですfloat
)。このサイズは、それぞれの 3 番目のパラメータ ( ) に
渡す必要があります。sride
glVertexPointer
glColorPointer
名前付きバッファ オブジェクトがバインドされている場合、glVertexPointer
それぞれの最後のパラメータはglColorPointer
、バッファ オブジェクトのバッファ ストアへのバイト オフセットとして扱われます。オフセットは、属性の最初のコンポーネントまでのバイト数です。オフセットが 0 の
場合は、属性タプルの最初のコンポーネントであるためです。オフセットが 3*4=12 バイトの場合は、3 つの座標の後にあり、各コンポーネントのサイズが 4 であるためです。最後のパラメーターの型はポインターであるため、オフセットをキャストする必要があります(例: )。この python 組み込みライブラリをインポートする必要があります。オフセットが 0 の場合、 の代わりに を使用できます。glVertexPointer
(x, y, z)
glColorPointer
(r, g, b)
(x, y, z)
ctypes.c_void_p
ctypes.c_void_p(3*4)
ctypes
None
ctypes.c_void_p(0)
頂点属性の仕様は次のようになります。
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()