Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems with wavefront object as GLMeshItem in Pyqtgraph #133

Closed
Cocco17 opened this issue Apr 12, 2021 · 6 comments
Closed

Problems with wavefront object as GLMeshItem in Pyqtgraph #133

Cocco17 opened this issue Apr 12, 2021 · 6 comments

Comments

@Cocco17
Copy link

Cocco17 commented Apr 12, 2021

Hi there!
I'm trying to use PyWavefront to read an wavefront object and visualise it using Pyqtgraph.
Using the faces and vertices data for GLLinePlotItem and GLScatterPlotItem works fine, but there seems to be a compatibility issue with the vertices and faces data with GLMeshItem:

> |==============================>>
>     |  Traceback (most recent call last):
>     |    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 197, in _run_module_as_main
>     |      return _run_code(code, main_globals, None,
>     |    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 87, in _run_code
>     |      exec(code, run_globals)
>     |    File "/Users/X/.vscode/extensions/ms-python.python-2021.3.680753044/pythonFiles/lib/python/debugpy/__main__.py", line 45, in <module>
>     |      cli.main()
>     |    File "/Users/X/.vscode/extensions/ms-python.python-2021.3.680753044/pythonFiles/lib/python/debugpy/../debugpy/server/cli.py", line 444, in main
>     |      run()
>     |    File "/Users/X/.vscode/extensions/ms-python.python-2021.3.680753044/pythonFiles/lib/python/debugpy/../debugpy/server/cli.py", line 285, in run_file
>     |      runpy.run_path(target_as_str, run_name=compat.force_str("__main__"))
>     |    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 268, in run_path
>     |      return _run_module_code(code, init_globals, run_name,
>     |    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 97, in _run_module_code
>     |      _run_code(code, mod_globals, init_globals,
>     |    File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/runpy.py", line 87, in _run_code
>     |      exec(code, run_globals)
>     |    File "/Users/X/test_pywavefront.py", line 45, in <module>
>     |      QtGui.QApplication.instance().exec_()
>     |    File "/Users/X/.venv/lib/python3.9/site-packages/pyqtgraph/opengl/GLViewWidget.py", line 257, in paintGL
>     |      self.drawItemTree(useItemNames=useItemNames)
>     |    File "/Users/X/.venv/lib/python3.9/site-packages/pyqtgraph/opengl/GLViewWidget.py", line 297, in drawItemTree
>     |      self.drawItemTree(i, useItemNames=useItemNames)
>     |    File "/Users/X/.venv/lib/python3.9/site-packages/pyqtgraph/opengl/GLViewWidget.py", line 278, in drawItemTree
>     |      debug.printExc()
>     |    --- exception caught here ---
>     |    File "/Users/X/.venv/lib/python3.9/site-packages/pyqtgraph/opengl/GLViewWidget.py", line 275, in drawItemTree
>     |      i.paint()
>     |    File "/Users/X/.venv/lib/python3.9/site-packages/pyqtgraph/opengl/items/GLMeshItem.py", line 167, in paint
>     |      self.parseMeshData()
>     |    File "/Users/X/.venv/lib/python3.9/site-packages/pyqtgraph/opengl/items/GLMeshItem.py", line 146, in parseMeshData
>     |      self.normals = md.vertexNormals(indexed='faces')
>     |    File "/Users/X/.venv/lib/python3.9/site-packages/pyqtgraph/opengl/MeshData.py", line 209, in vertexNormals
>     |      faceNorms = self.faceNormals()
>     |    File "/Users/X/.venv/lib/python3.9/site-packages/pyqtgraph/opengl/MeshData.py", line 188, in faceNormals
>     |      self._faceNormals = np.cross(v[:,1]-v[:,0], v[:,2]-v[:,0])
>     |  TypeError: list indices must be integers or slices, not tuple
>     |==============================<<
> Error while drawing item <pyqtgraph.opengl.items.GLMeshItem.GLMeshItem object at 0x7f82a86dbdc0>.

Does anybody try to use PyWavefront in combination with Pyqtgraph already? Can any body help me to find the problem and a solution? Looking forward for some help, thanks a lot in advance!

The code:

  import pywavefront
  from pyqtgraph.Qt import QtCore, QtGui
  import pyqtgraph as pg
  import pyqtgraph.opengl as gl
  import numpy as np
  
  scene = pywavefront.Wavefront(
      "/BMW_simple.obj",
      strict=False,
      create_materials=True,
      collect_faces=True
  )
  
  print("Faces:", scene.mesh_list[0].faces)
  print("Vertices:", scene.vertices)
  print("Format:", scene.mesh_list[0].materials[0].vertex_format)
  print("Vertices:", scene.mesh_list[0].materials[0].vertices)
  
  app = QtGui.QApplication([])
  w = gl.GLViewWidget()
  w.show()
  w.setWindowTitle('pyqtgraph example: GLMeshItem')
  w.setCameraPosition(distance=40)
  
  g = gl.GLGridItem()
  g.scale(2,2,1)
  w.addItem(g)
  
  m1 = gl.GLMeshItem(vertexes=scene.vertices, drawFaces=False, drawEdges=True, smooth=True)
  m1.translate(5, 5, 0)
  m1.setGLOptions('additive')
  w.addItem(m1)
  
  pts2 = np.array(scene.vertices)
  sh2 = gl.GLLinePlotItem(pos=pts2, mode='line_strip')
  sh3 = gl.GLScatterPlotItem(pos=pts2)
  w.addItem(sh2)
  w.addItem(sh3)
  
  
  ## Start Qt event loop unless running in interactive mode.
  if __name__ == '__main__':
      import sys
      if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
          QtGui.QApplication.instance().exec_()
@greenmoss
Copy link
Collaborator

Hello, thanks for the bug report!

A few questions/requests:

Did you launch your command from a command line? If so, are you able to include the full command you used to launch, as well as reformatting the output to Markdown? You can use the same "```" technique as you used for the script contents.

Are you also able to include the contents of BMW_simple.obj?

Thanks!

@Cocco17
Copy link
Author

Cocco17 commented Apr 13, 2021

Hi @greenmoss! Thanks for the quick reply.

The commands are part a Jupyter notebook that I use to test parts of my code before applying them in my main code.

I just edited the output accordingly, sorry about that!

Attached you can find the Wavefront model - it's a model from the www that I simplified using Blender and exporting it to a wavefront object.

Another weird thing that is happening: In Blender I could choose the Forward and Top Axis, which I have chosen to be the same as in my GLViewWidget. However, when importing the model as a GLLinePlot, the model is rotate 90° to the left of the x-axis. Using the rotating function seems to fail as the model is then not shown anymore.. But I guess that is an issue with pyqtgraph, isn't it?

BMW_Easy.obj.zip

@greenmoss
Copy link
Collaborator

Thanks for the reformat!

Looking at your code, there are some print statements. Are those part of the output as well?

I don't have experience with Jupyter or Pyqtgraph. Based on the stack trace, I'd think File "/Users/X/test_pywavefront.py", line 45 is the place to look. Presumably that is line 45 of your code above?

Some things to try:

  • See if you can draw your BMW_Easy.obj file with PyWavefront only. There are some example renderers in the examples directory.
  • I'm guessing the output from PyWavefront is in tuples, but your pyqtgraph.opengl.GLMeshItem is expecting a different format. See if you can transform the output from PyWavefront to the format expected by pyqtgraph. Maybe an array/list?

@Cocco17
Copy link
Author

Cocco17 commented Apr 15, 2021

Thanks for your input! Just managed to transform the outputs in the suitable format for PyQtGraph (extracted all faces into a separate array).

(Print statements are just for debugging purposes.. I have used one of the examples and exchanged the model and it works fine, so the problem is definitely due to format issues...)

@Cocco17 Cocco17 closed this as completed Apr 15, 2021
@nitieaj
Copy link

nitieaj commented Jun 10, 2021

Thanks for your input! Just managed to transform the outputs in the suitable format for PyQtGraph (extracted all faces into a separate array)

@Cocco17 Pls Can you point me in the right direction to towards how you managed to transform the output in the suitable format for pyqtgraph. ? I`m having simiar issues.

@Cocco17
Copy link
Author

Cocco17 commented Jun 14, 2021

Hi @nitieaj! Sorry for the late response, had a few days of vacation.
This is the code I used to transform the pywavefront object to a plot in pyqtgraph:

        # Vehicle
        vehicle = scene = pywavefront.Wavefront('./vehicle.obj', strict=False, create_materials=True, collect_faces=True)#, cache=True) # Cache is currently not working?!

        # Conversion - Pywavefront to PyQtGraph GLMeshItem
        vertices_array = np.asarray(vehicle.vertices)
        faces_array = []
        for mesh_lists in vehicle.mesh_list:
            for faces in mesh_lists.faces:
                faces_array.append(np.array([faces[0],faces[1],faces[2]]))
        faces_array = np.asarray(faces_array)
        
        # Plotting the data in PyQtGraph
        vehicleMesh = gl.MeshData(vertexes=vertices_array, faces=faces_array)
        vehicleGL = gl.GLMeshItem(meshdata=vehicleMesh, drawEdges=True, edgeColor=(0,1,0,1), smooth=True)
        vehicleGL.scale(100,100,100)
        self.graphicsView.addItem(vehicleGL)
        self.graphicsView_viewResults.addItem(vehicleGL)

However, I did not manage to add the textures/materials of the model. I'm not sure whether this is possible or not with PyQtGraph - if you find a way, please let me know!

Furthermore, the cache function in pywavefront has not been working for me. The created binary file cannot be processed after its creation - again, if you find a solution, happy to hear back from you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants