亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用現代 OpenGL 繪圖時的點云失真

使用現代 OpenGL 繪圖時的點云失真

小怪獸愛吃肉 2023-03-16 11:27:26
我找到了使用 PyQt 和現代 OpenGL 繪制和旋轉立方體的精彩教程。我的目標是通過執行以下操作來為點云調整腳本(另請參見下面的代碼):使用 Open3D 加載點云并將坐標和顏色提取為 numpy 數組從數組創建頂點緩沖區對象 (VBO)將繪圖功能更改為gl.glDrawElements(gl.GL_POINTS, ...)不幸的是,點云非常扭曲和稀?。ㄒ娊貓D)。它實際上應該是一個有椅子和墻壁的房間。你看我是否在 VBO 或繪圖上犯了錯誤?還是有更好的加載點云的方法?我用舊的固定管道(glBegin(GL_POINTS)... glEnd())測試了這個例子,點云被正確繪制(但性能也很差?。?
查看完整描述

1 回答

?
慕慕森

TA貢獻1856條經驗 獲得超17個贊

經過長時間的搜索,我發現了這個stackoverflow-postgl.glGenBuffers(1)我通過將點坐標和顏色一起存儲在一個 vbo 對象 ( )中來調整我的代碼以適應該答案。然后我用特定的步幅和偏移量定義頂點和顏色指針:

  • gl.glVertexPointer(3, gl.GL_FLOAT, 6*4, None)

    • 步幅= 24 字節:[x, y, z, r, g, b] * sizeof(float)

  • gl.glColorPointer(3, gl.GL_FLOAT, 6*4, ctypes.c_void_p(3*4))

    • offset= 12 bytes:rgb顏色從3個坐標x,y,z之后開始

最后我用來gl.glDrawArrays(gl.GL_POINTS, 0, noOfVertices)繪制點云。

完整代碼如下(標有### NEW ###注釋):

from PyQt5 import QtCore      # core Qt functionality

from PyQt5 import QtGui       # extends QtCore with GUI functionality

from PyQt5 import QtOpenGL    # provides QGLWidget, a special OpenGL QWidget

from PyQt5 import QtWidgets


import OpenGL.GL as gl        # python wrapping of OpenGL

from OpenGL import GLU        # OpenGL Utility Library, extends OpenGL functionality

from OpenGL.arrays import vbo

import numpy as np

import open3d as o3d

import ctypes 

import sys                    # we'll need this later to run our Qt application


class MainWindow(QtWidgets.QMainWindow):


    def __init__(self):

        QtWidgets.QMainWindow.__init__(self)    # call the init for the parent class


        self.resize(300, 300)

        self.setWindowTitle('Hello OpenGL App')

        

        self.glWidget = GLWidget(self)

        self.initGUI()

        

        timer = QtCore.QTimer(self)

        timer.setInterval(20)   # period, in milliseconds

        timer.timeout.connect(self.glWidget.updateGL)

        timer.start()

        

    def initGUI(self):

        central_widget = QtWidgets.QWidget()

        gui_layout = QtWidgets.QVBoxLayout()

        central_widget.setLayout(gui_layout)


        self.setCentralWidget(central_widget)


        gui_layout.addWidget(self.glWidget)


        sliderX = QtWidgets.QSlider(QtCore.Qt.Horizontal)

        sliderX.valueChanged.connect(lambda val: self.glWidget.setRotX(val))


        sliderY = QtWidgets.QSlider(QtCore.Qt.Horizontal)

        sliderY.valueChanged.connect(lambda val: self.glWidget.setRotY(val))


        sliderZ = QtWidgets.QSlider(QtCore.Qt.Horizontal)

        sliderZ.valueChanged.connect(lambda val: self.glWidget.setRotZ(val))


        gui_layout.addWidget(sliderX)

        gui_layout.addWidget(sliderY)

        gui_layout.addWidget(sliderZ)

        

class GLWidget(QtOpenGL.QGLWidget):

    def __init__(self, parent=None):

        self.parent = parent

        QtOpenGL.QGLWidget.__init__(self, parent)


    def initializeGL(self):

        self.qglClearColor(QtGui.QColor(100, 100, 100))     # initialize the screen to blue

        gl.glEnable(gl.GL_DEPTH_TEST)                       # enable depth testing


        self.initGeometry()


        self.rotX = 0.0

        self.rotY = 0.0

        self.rotZ = 0.0


    def setRotX(self, val):

        self.rotX = val


    def setRotY(self, val):

        self.rotY = val


    def setRotZ(self, val):

        self.rotZ = val

        

    def resizeGL(self, width, height):

        gl.glViewport(0, 0, width, height)

        gl.glMatrixMode(gl.GL_PROJECTION)

        gl.glLoadIdentity()

        aspect = width / float(height)


        GLU.gluPerspective(45.0, aspect, 1.0, 100.0)

        gl.glMatrixMode(gl.GL_MODELVIEW)

        

    def paintGL(self):

        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)


        gl.glPushMatrix()    # push the current matrix to the current stack


        gl.glTranslate(0.0, 0.0, -3.0)    # third, translate cube to specified depth

        #gl.glScale(20.0, 20.0, 20.0)       # second, scale cube

        gl.glRotate(self.rotX, 1.0, 0.0, 0.0)

        gl.glRotate(self.rotY, 0.0, 1.0, 0.0)

        gl.glRotate(self.rotZ, 0.0, 0.0, 1.0)

        gl.glTranslate(-0.5, -0.5, -0.5)   # first, translate cube center to origin


        # Point size

        gl.glPointSize(3)

        

        ### NEW ###

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vbo)


        stride = 6*4 # (24 bates) : [x, y, z, r, g, b] * sizeof(float)


        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)

        gl.glVertexPointer(3, gl.GL_FLOAT, stride, None)


        gl.glEnableClientState(gl.GL_COLOR_ARRAY)

        offset = 3*4 # (12 bytes) : the rgb color starts after the 3 coordinates x, y, z 

        gl.glColorPointer(3, gl.GL_FLOAT, stride, ctypes.c_void_p(offset))

        

        noOfVertices = self.noPoints

        gl.glDrawArrays(gl.GL_POINTS, 0, noOfVertices)


        gl.glDisableClientState(gl.GL_VERTEX_ARRAY)

        gl.glDisableClientState(gl.GL_COLOR_ARRAY)

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)

        ### NEW ###


        gl.glPopMatrix()    # restore the previous modelview matrix

        


    def initGeometry(self):

    

        vArray = self.LoadVertices()

        self.noPoints  = len(vArray) // 6

        print("No. of Points: %s" % self.noPoints)

        

        self.vbo = self.CreateBuffer(vArray)


        

    ### NEW ###


    def LoadVertices(self):

        

        pcd = o3d.io.read_point_cloud("../pointclouds/0004.ply")

        print(pcd)

        print("Pointcloud Center: " + str(pcd.get_center()))

    

        points = np.asarray(pcd.points).astype('float32')

        colors = np.asarray(pcd.colors).astype('float32')

        

        attributes = np.concatenate((points, colors),axis=1)

        print("Attributes shape: " + str(attributes.shape))

        

        return attributes.flatten()


    def CreateBuffer(self, attributes):

        bufferdata = (ctypes.c_float*len(attributes))(*attributes) # float buffer

        buffersize = len(attributes)*4                             # buffer size in bytes 


        vbo = gl.glGenBuffers(1)

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vbo)

        gl.glBufferData(gl.GL_ARRAY_BUFFER, buffersize, bufferdata, gl.GL_STATIC_DRAW) 

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0)

        return vbo

        

    ### NEW ###



if __name__ == '__main__':


    app = QtWidgets.QApplication(sys.argv)


    win = MainWindow()

    win.show()


    sys.exit(app.exec_())

但是,我仍然沒有為上面的初始方法找到正確的參數,其中兩個單獨的 VBO 用于坐標和顏色。所以我很高興收到進一步的評論。


查看完整回答
反對 回復 2023-03-16
  • 1 回答
  • 0 關注
  • 119 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號