Skip to content

Instantly share code, notes, and snippets.

@notaTeapot
Last active April 29, 2024 20:12
Show Gist options
  • Save notaTeapot/5feea53dccc921ea6af88a4d222e1e2b to your computer and use it in GitHub Desktop.
Save notaTeapot/5feea53dccc921ea6af88a4d222e1e2b to your computer and use it in GitHub Desktop.
Open 3d Widget with editing
# Partially Working Error on Exit
from PySide2 import QtWidgets, QtGui,QtCore
import open3d as o3d
import win32gui
import sys
import threading
import time
class Worker(QtCore.QObject):
def run(self,vis):
vis.run()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
widget = QtWidgets.QWidget()
layout = QtWidgets.QGridLayout(widget)
self.setCentralWidget(widget)
file_path = "C:\\test\test.pcd"
self.pcd = o3d.io.read_point_cloud(file_path)
self.vis = o3d.visualization.VisualizerWithEditing()
self.vis.create_window()
self.vis.add_geometry(self.pcd)
hwnd = win32gui.FindWindowEx(0, 0, None, "Open3D - free view")
self.window = QtGui.QWindow.fromWinId(hwnd)
self.windowcontainer = self.createWindowContainer(self.window, widget)
layout.addWidget(self.windowcontainer, 0, 0)
self.thread = QtCore.QThread()
self.worker = Worker()
self.thread.started.connect(lambda: self.worker.run(self.vis))
self.thread.start()
timer = QtCore.QTimer(self)
timer.timeout.connect(self.blub)
timer.start(100)
#print("starting vis")
btn = QtWidgets.QPushButton(text="test")
btn.clicked.connect(lambda: print("Button pressed!"))
layout.addWidget(btn)
def blub(self):
#Function to keep PySide eventloop running
pass
def start_vis(self):
print("thread start")
self.vis.run()
print("thread end")
def update_vis(self):
#self.vis.update_geometry()
self.vis.poll_events()
self.vis.update_renderer()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
form = MainWindow()
form.setWindowTitle('o3d Embed')
form.setGeometry(100, 100, 600, 500)
form.show()
sys.exit(app.exec_())
@M-A-X-P-Y
Copy link

M-A-X-P-Y commented Apr 29, 2024

Could anyone hint me on how this code could be changed to visualize a .OBJ or .PLY file with texture? (still using VisualizerWithEditing() within a Qt widget)
Here is what I have been able to achieve (and not):

  • using o3d.io.read_triangle_mesh() on a .PLY file instead of o3d.io.read_point_cloud() for a .PCD brings the object with texture in the visualizer, but then clicking does not do anything.

  • using o3d.io.read_triangle_mesh() on a .OBJ brings the object but does not load the texture, and again clicking does not do anything.

  • using o3d.io.read_triangle_model() yields an error as self.vis.add_geometry() does not support "triangle_model" object type. self.vis Class only has add_geometry(), and does not support add_model() as some other open3d classes have.

I am thinking about finding a way to convert the OBJ or PLY object to a point-cloud (with texture) in open3d and then loading it into the visualizer as a workaround if no other way exists (and need to figure out how to perform that conversion).
[Edit] I converted a textured mesh (.PLY) to point-count simply with the following:
filepath1 = 'my_filepath_to_my_ply_file'
obj1 = o3d.io.read_triangle_mesh(filepath1)
pcd = o3d.geometry.PointCloud()
pcd.points = obj1.vertices
pcd.colors = obj1.vertex_colors
pcd.normals = obj1.vertex_normals
It is not ideal as clicking between points results in "no click", or may hit a point located on a face behind the intended face.
It also seems that VisualizerWithEditing() ignores further add_geometry() calls, so it is not possible to have more than one object in the visualizer.

I am thinking it may then be best to use the standard open3d visualizer and use ray_casting to identify the location where the user clicked.
https://www.open3d.org/docs/release/tutorial/geometry/ray_casting.html#Creating-a-virtual-point-cloud
Anyone tried doing that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment