pyQt5中的pyOpenGL-点云渲染中的相机位置

问题描述 投票:1回答:1

这是我关于stackoverflow的第一个问题,对于任何错误,我们深表歉意,但是现在我不知道如何处理我的问题。我正在编写一个在pyQt5中使用OpenGl渲染点云的应用程序。我可以使用VBO渲染所有点,但是查看点的唯一方法是将其坐标标准化为-0.5-0.5值。您能帮我解决这个问题吗?

这是我的代码:

def initializeGL(self):
    self.setClearColor(self.backgroundColor)
    self.object = self.makeDefaultObject()
    if not self.drawDefaultData and self.pts.size == 0: self.pts = default.pointCloud
    gl.glShadeModel(gl.GL_FLAT)
    gl.glEnable(gl.GL_DEPTH_TEST)
    gl.glEnable(gl.GL_CULL_FACE)
    self.reloadPoints()
def reloadPoints(self):
    if self.pts.size == 0:
        self.pts = default.pointCloud 
    self.vbo_disp, self.vbo_disp_clr, self.disp_count = self.loadVBO()
    self.xPos = -np.mean(self.pts, axis=0)[0]
    self.yPos = np.mean(self.pts, axis=0)[1]
    self.zPos = np.min(self.pts, axis=0)[2] -10
def paintGL(self):
    gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
    gl.glLoadIdentity()
    gl.glTranslated(self.xPos, self.yPos, self.zPos)
    gl.glScaled(self.zoomScale, self.zoomScale, self.zoomScale)
    gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
    gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
    gl.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
    gl.glCallList(self.object)
    if self.pts.size != 0: self.drawPointCloud()
def resizeGL(self, width, height):
    side = min(width, height)
    if side < 0:
        return

    gl.glViewport((width - side) // 2, (height - side) // 2, side,
                  side)

    gl.glMatrixMode(gl.GL_PROJECTION)
    gl.glLoadIdentity()
    gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
    gl.glMatrixMode(gl.GL_MODELVIEW)
def drawPointCloud(self):
    gl.glPushMatrix()
    gl.glPointSize(self.pointSize)   
    glEnableClientState(gl.GL_VERTEX_ARRAY)
    glEnableClientState(gl.GL_COLOR_ARRAY)

    vtx_disp = self.vbo_disp[0]
    clr_disp = self.vbo_disp_clr[0]
    cnt_disp = self.disp_count[0]

    vtx_disp.bind()
    gl.glVertexPointer(3, gl.GL_FLOAT, 0, vtx_disp)
    vtx_disp.unbind()

    clr_disp.bind()
    gl.glColorPointer(3, gl.GL_FLOAT, 0, clr_disp)
    clr_disp.unbind()

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

    glDisableClientState(gl.GL_VERTEX_ARRAY)
    glDisableClientState(gl.GL_COLOR_ARRAY)

    gl.glPopMatrix()
def loadVBO(self):
    vtx_list = [ [] for _ in range(1) ]
    clr_list = [ [] for _ in range(1) ]        
    vtx_count = np.zeros( 1, dtype=np.int32 ) 

    vtx_count[0] = len(self.pts)
    vtx_list[0] = qlVBO.VBO( self.pts[:,:3].copy().astype(np.float32) )
    if (np.size(self.pts, 1) == 6):
        clr_list[0] = qlVBO.VBO( self.pts[:,3:].copy().astype(np.float32) / 255.0 )
    elif (np.size(self.pts, 1) == 3):
        clr_list[0] = qlVBO.VBO( np.ones([vtx_count[0],3]).astype(np.float32) )
    else:
        print("Internal error")
    vtx_count[0] = len(self.pts)

    return vtx_list, clr_list, vtx_count

我一直在尝试更改相机的放置方式,但没有任何结果。我认为问题出在:

gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)

但是如何更改...请帮助我!

python qt opengl pyqt5 pyopengl
1个回答
0
投票

您可以在视口上看到的是3D视区的投影。投影矩阵定义相对于投影到视口的观察者(观察者)的区域(体积)。在您的情况下,请使用Orthographic projection。在正交投影时,此区域(体积)由到观看者位置的6个距离(左,右,下,上,近和远)定义。空间(体积)中的所有对象(点)在视口上都是“可见的”。超出此空间的所有对象(点)将被裁剪到体积的边界。

[...]但查看点的唯一方法是将其坐标标准化为-0.5-0.5值[...]

实际上,您以错误的方式进行操作。您可以更改顶点坐标(点)的比例,而不是扩大查看量。正交投影可以通过glOrtho设置:

glOrtho

此设置定义了一个长方体体积,其左侧,底部,附近od(-0.5,-0.5、4.0)和右侧,顶部,远处(0.5、0.5、15.0)。增加音量,而不是缩放坐标:

gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)

我建议您执行以下操作:

计算点云的轴对齐边界框,从(gl.glOrtho(min_x, max_x, max_y, min_y, min_z, max_z) self.min_xself._min_y)到(self.min_zself.max_xself._max_y)并定义正交投影,该投影定义了长方体的体积,足够大以包围所有独立于其方向的点(self.max_z):

Euclidean distance

计算边界框的中心并定义相反方向的初始平移。翻译必须将点云的中心“移动”到世界的起源:

ef resizeGL(self, width, height):
    side = min(width, height)
    if side < 0:
        return
    gl.glViewport((width - side) // 2, (height - side) // 2, side, side)

    dx = self.max_x - self.min_x
    dy = self.max_y - self.min_y
    dz = self.max_z - self.min_z
    dia = math.sqrt(dx*dx + dy*dy, + dz*dz)

    gl.glMatrixMode(gl.GL_PROJECTION)
    gl.glLoadIdentity()
    gl.glOrtho(-dia/2, dia/2, dia/2, -dia/2, -dia/2, dia/2)
    gl.glMatrixMode(gl.GL_MODELVIEW)

观看量足够大,因此没有必要缩放点(self.xPos = -(self.min_x + self.max_x) / 2 self.yPos = -(self.min_y + self.max_y) / 2 self.zPos = -(self.min_z + self.max_z) / 2 )。首先缩放点云,然后进行平移并最终旋转,这一点很重要,因此旋转的枢轴是点云的中心:

self.zoomScale = 1

modelview = rotation * scale * translationToOrigin glRotateglRotate之类的矩阵变换操作定义一个新矩阵,并将当前矩阵乘以该新矩阵。因此,操作顺序必须为1. glScale,2。glScale,3。glTranslate,:

glTranslate
© www.soinside.com 2019 - 2024. All rights reserved.