title: Point Cloud Distortion when Drawing with modern OpenGL
body: <p>I found this <a href="https://nrotella.github.io/journal/first-steps-python-qt-opengl.html" rel="nofollow noreferrer">nice tutorial</a> of drawing and rotating a cube with PyQt and modern OpenGL. My objective was to adapt the script for point clouds, by doing the following (see also code below):</p>
  <ol>
  <li>Load point cloud using Open3D and extract coordinates &amp; colors as numpy arrays</li>
  <li>Create Vertex Buffer Objects (VBOs) from the arrays</li>
  <li>Change the drawing function to <code>gl.glDrawElements(gl.GL_POINTS, ...)</code></li>
  </ol>
  <p>Unfortunately then the point cloud is very distorted and thin (see screenshot). It should actually be a room with chairs and walls.</p>
  <p><strong>Do you see if I made a mistake with the VBOs or drawing? Or is there a better way of loading a point cloud?</strong></p>
  <p><a href="https://i.stack.imgur.com/9vr4F.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/9vr4F.png" alt="Example of distorted point cloud with modern approach" /></a></p>
  <p>I tested the example with the old fixed pipeline (<code>glBegin(GL_POINTS)</code> ... <code>glEnd()</code>) and there the point cloud is correctly drawn (but also the performance really bad!).</p>
  <pre><code>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 sys
  
  # Loading the point cloud from file
  def load_pointcloud():
      pcd = o3d.io.read_point_cloud(&quot;../pointclouds/0004.ply&quot;)
      print(pcd)
      print(&quot;Pointcloud Center: &quot; + str(pcd.get_center()))
      points = np.asarray(pcd.points)
      colors = np.asarray(pcd.colors)
  
      return points, colors
  
  #### here was only the GUI code (slider, ...) , which works fine! ####
          
  class GLWidget(QtOpenGL.QGLWidget):
      def __init__(self, parent=None):
          self.parent = parent
          QtOpenGL.QGLWidget.__init__(self, parent)
  
      def initializeGL(self):
          self.qglClearColor(QtGui.QColor(250, 250, 250))     # initialize the screen to blue
          gl.glEnable(gl.GL_DEPTH_TEST)                   # enable depth testing
  
          self.initGeometryPC()
  
          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)   #GLU.gluPerspective(45.0, aspect, 1.0, 100.0)
          gl.glOrtho(-2.0, 2.0, -2.0, 2.0, 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, -5.0)          # third, translate cube to specified depth
          #gl.glScale(.5, .5, .5)                 # second, scale point cloud
          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 point cloud center to origin
  
          gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
          gl.glEnableClientState(gl.GL_COLOR_ARRAY)
  
          gl.glVertexPointer(3, gl.GL_FLOAT, 0, self.vertVBO)
          gl.glColorPointer(3, gl.GL_FLOAT, 0, self.colorVBO)
  
          gl.glPointSize(2)
          gl.glDrawElements(gl.GL_POINTS, len(self.pointsIdxArray), gl.GL_UNSIGNED_INT, self.pointsIdxArray)
          
          gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
          gl.glDisableClientState(gl.GL_COLOR_ARRAY)
  
          gl.glPopMatrix()    # restore the previous modelview matrix
          
      # Push geometric data to GPU
      def initGeometryPC(self):
          points, colors = load_pointcloud()
      
          self.pointsVtxArray = points
          self.vertVBO = vbo.VBO(np.reshape(self.pointsVtxArray, (1, -1)).astype(np.float32))
          self.vertVBO.bind()
          
          self.pointsClrArray = colors
          self.colorVBO = vbo.VBO(np.reshape(self.pointsClrArray, (1, -1)).astype(np.float32))
          self.colorVBO.bind()
          
          self.pointsIdxArray = np.arange(len(points))
  
  
  if __name__ == '__main__':
      app = QtWidgets.QApplication(sys.argv)
      win = MainWindow()
      win.show()
      sys.exit(app.exec_())
  </code></pre>