首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >pyOpenGL在pyQt5中的位置-在点云渲染中

pyOpenGL在pyQt5中的位置-在点云渲染中
EN

Stack Overflow用户
提问于 2020-04-13 08:34:06
回答 1查看 498关注 0票数 1

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

这是我的密码:

代码语言:javascript
复制
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

我一直试图改变相机的定位方式,但没有任何结果。我认为问题在于:

代码语言:javascript
复制
gl.glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)

但如何改变这种状况..。请帮我一把!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-13 08:49:34

您可以在视口上看到的是三维视图卷的投影。投影矩阵定义了相对于投影到视口的观察者(查看者)的面积(体积)。

在您的例子中,您使用了一个正射投影。在正射投影中,这个区域(体积)由6个距离(左、右、下、上、近和远)定义。空间(卷)中的所有对象(点)在视口上都是“可见的”。在这个空间之外的所有对象(点)都被裁剪在卷的边框上。

..。但看到点的唯一方法是将坐标正常化为-0.5 - 0.5值.

其实你做错了。您可以更改顶点坐标(点)的比例,而不是扩展查看量。

正投影可由glOrtho设定。

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

这个设置定义了一个长方体体积与左,底部,接近od (-0.5,-0.5,4.0)和右,顶部,远的(0.5,0.5,15.0)。

增加这个体积,而不是缩放坐标:

代码语言:javascript
复制
gl.glOrtho(min_x, max_x, max_y, min_y, min_z, max_z)

我建议采取以下措施:

计算点云的轴对齐包围框,从(self.min_xself._min_yself.min_z)到(self.max_xself._max_yself.max_z),并定义一个正正转投影,该投影定义一个长方体体积,其大小足以将所有与其方向无关的点(欧氏距离)包围起来:

代码语言:javascript
复制
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)

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

代码语言:javascript
复制
self.center_x = (self.min_x + self.max_x) / 2
self.center_y = (self.min_y + self.max_y) / 2
self.center_z = (self.min_z + self.max_z) / 2
代码语言:javascript
复制
self.xPos = 0
self.yPos = 0
self.zPos = 0

观看量足够大,因此没有必要缩放点(self.zoomScale = 1)。首先对点云进行缩放,然后将其平移并最终旋转是很重要的,因此旋转的支点是点云的中心:

代码语言:javascript
复制
modelview = translate * rotation * scale * translateToOrigin 

glRotateglScaleglTranslate等矩阵变换操作定义了一个新矩阵,并将当前矩阵与新矩阵相乘。因此,操作的顺序必须是1. glTranslate 2. glRotate,3. glScale,4. glTranslate(-center),:

代码语言:javascript
复制
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.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
    gl.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
    gl.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)

    gl.glScaled(self.zoomScale, self.zoomScale, self.zoomScale)

    gl.glTranslated(-self.center_x, -self.center_y, -self.center_z)

    # [...]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61184158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档