Home > Net >  Why does Open3d Visualization disappear when I left click the window?
Why does Open3d Visualization disappear when I left click the window?

Time:04-08

I try to write a simple application in python which views a 3d mesh on the right and have some user input on the left in a single window.

I use a SceneWidget to visualize a mesh and add it to a horizontal gui element. I also add a filepicker to that gui element and then add the gui element to the window. So far so good it seems that it works as intended but as soon as I make a left click inside the window the visualization disappears with no error message. Does anyone have an idea why and can help me? Short video of the application - visualization stops by leftclick

Here is the code:

import os.path
import sys

import open3d as o3d
import open3d.visualization.gui as gui
import open3d.visualization.rendering as rendering

print("Project")
print("python version", sys.version)
print("open3d version", o3d.__version__)

class WindowApp:

    def __init__(self):
        self.window = gui.Application.instance.create_window("Project", 1400, 900)
        w = self.window

        # member variables
        self.model_dir = ""
        self.model_name = ""
        
        em = w.theme.font_size
        layout = gui.Horiz(0, gui.Margins(0.5 * em, 0.5 * em, 0.5 * em, 0.5 * em))
        # 3D Widget
        _widget3d = gui.SceneWidget()
        _widget3d.scene = rendering.Open3DScene(w.renderer)
        _widget3d.set_view_controls(gui.SceneWidget.Controls.ROTATE_CAMERA)
        mesh = o3d.geometry.TriangleMesh.create_sphere()
        mesh.compute_vertex_normals()
        material = rendering.MaterialRecord()
        material.shader = "defaultLit"
        _widget3d.scene.add_geometry('mesh', mesh, material)
        _widget3d.scene.set_background([200, 0, 0, 200]) # not working?!
        _widget3d.scene.camera.look_at([0, 0, 0], [1, 1, 1], [0, 0, 1])
        _widget3d.set_on_mouse(self._on_mouse_widget3d)

        # gui layout
        gui_layout = gui.Vert(0, gui.Margins(0.5 * em, 0.5 * em, 0.5 * em, 0.5 * em))
        # File-chooser widget
        self._fileedit = gui.TextEdit()
        filedlgbutton = gui.Button("...")
        filedlgbutton.horizontal_padding_em = 0.5
        filedlgbutton.vertical_padding_em = 0
        filedlgbutton.set_on_clicked(self._on_filedlg_button)

        fileedit_layout = gui.Horiz()
        fileedit_layout.add_child(gui.Label("Model file"))
        fileedit_layout.add_child(self._fileedit)
        fileedit_layout.add_fixed(0.25 * em)
        fileedit_layout.add_child(filedlgbutton)
        # add to the top-level (vertical) layout
        gui_layout.add_child(fileedit_layout)

        layout.add_child(gui_layout)
        layout.add_child(_widget3d)
        w.add_child(layout)

    def _on_mouse_widget3d(self, event):
        print(event.type)
        return gui.Widget.EventCallbackResult.IGNORED

    def _on_filedlg_button(self):
        filedlg = gui.FileDialog(gui.FileDialog.OPEN, "Select file",
                                 self.window.theme)
        filedlg.add_filter(".obj .ply .stl", "Triangle mesh (.obj, .ply, .stl)")
        filedlg.add_filter("", "All files")
        filedlg.set_on_cancel(self._on_filedlg_cancel)
        filedlg.set_on_done(self._on_filedlg_done)
        self.window.show_dialog(filedlg)

    def _on_filedlg_cancel(self):
        self.window.close_dialog()

    def _on_filedlg_done(self, path):
        self._fileedit.text_value = path
        self.model_dir = os.path.normpath(path)
        # load model
        self.window.close_dialog()

def main():
    gui.Application.instance.initialize()
    w = WindowApp()
    gui.Application.instance.run()

if __name__ == "__main__":
    main()

I use the open3d library version 0.15.1 and python3.9.

Note - If I add the SceneWidget directly to the window it works, but then I can't have the gui on the left.

Does anyone have a solution to this?

CodePudding user response:

Finally I found a solution: Adding a Scenewidget to a gui container doesn't seem to work. But encapsulating it inside a frame and move it to the right side and add it directly to the window works. _widget3d.frame = gui.Rect(500, w.content_rect.y, 900, w.content_rect.height) Creating a frame for the gui in a similar way is also possible.

Here is the working code for anyone interested:

class WindowApp:

    def __init__(self):
        self.window = gui.Application.instance.create_window("Spinnables", 1400, 900)
        w = self.window

        # member variables
        self.model_dir = ""
        self.model_name = ""

        em = w.theme.font_size
        # 3D Widget
        _widget3d = gui.SceneWidget()
        _widget3d.scene = rendering.Open3DScene(w.renderer)
        _widget3d.set_view_controls(gui.SceneWidget.Controls.ROTATE_CAMERA)
        # create a frame that encapsulates the Scenewidget
        _widget3d.frame = gui.Rect(500, w.content_rect.y,
                                        900, w.content_rect.height)
        mesh = o3d.geometry.TriangleMesh.create_sphere()
        mesh.compute_vertex_normals()
        material = rendering.MaterialRecord()
        material.shader = "defaultLit"
        _widget3d.scene.add_geometry('mesh', mesh, material)
        _widget3d.scene.set_background([200, 0, 0, 200]) # not working?!
        _widget3d.scene.camera.look_at([0, 0, 0], [1, 1, 1], [0, 0, 1])
        _widget3d.set_on_mouse(self._on_mouse_widget3d)

        # gui layout
        gui_layout = gui.Vert(0, gui.Margins(0.5 * em, 0.5 * em, 0.5 * em, 0.5 * em))
        # create frame that encapsulates the gui
        gui_layout.frame = gui.Rect(w.content_rect.x, w.content_rect.y,
                                    500, w.content_rect.height)
        # File-chooser widget
        self._fileedit = gui.TextEdit()
        filedlgbutton = gui.Button("...")
        filedlgbutton.horizontal_padding_em = 0.5
        filedlgbutton.vertical_padding_em = 0
        filedlgbutton.set_on_clicked(self._on_filedlg_button)

        fileedit_layout = gui.Horiz()
        fileedit_layout.add_child(gui.Label("Model file"))
        fileedit_layout.add_child(self._fileedit)
        fileedit_layout.add_fixed(0.25 * em)
        fileedit_layout.add_child(filedlgbutton)
        # add to the top-level (vertical) layout
        gui_layout.add_child(fileedit_layout)

        w.add_child(gui_layout)
        w.add_child(_widget3d)
  • Related