How to embed opencascade V3d_View in gtkmm widget

625 Views Asked by At

I'm trying to port the code from https://github.com/eryar/occQt to gtkmm, by creating a custom widget and overriding the Gtk::widget::on_realize() method like

void OccView::on_realize() {
    // Create Aspect_DisplayConnection
    Handle(Aspect_DisplayConnection) display_connection = new Aspect_DisplayConnection();

    // Get graphic driver if it exists, otherwise initialize it.
    Handle(Graphic3d_GraphicDriver) graphic_driver;
    if (!graphic_driver) {
        graphic_driver = new OpenGl_GraphicDriver(display_connection);
    }

     // Get window handle. This returns something suitable for all platforms.
    Window x_window = GDK_SURFACE_XID(get_native()->get_surface()->gobj());

    // Create window for platform.
    Handle(Xw_Window) xw_window = new Xw_Window(display_connection, x_window);

    // Create V3dViewer and V3d_View
    mViewer = new V3d_Viewer(graphic_driver, Standard_ExtString("viewer3d"));
    mView = mViewer->CreateView();

    // Set window for the view
    mView->SetWindow(xw_window);
    if (!xw_window->IsMapped()) {
        xw_window->Map();
    }

    // Create AISInteractiveContext
    mContext = new AIS_InteractiveContext(mViewer);

    // Set up lights etc
    mViewer->SetDefaultLights();
    mViewer->SetLightOn();

    mView->SetBackgroundColor(Quantity_NOC_BLACK);
    mView->MustBeResized();
    mView->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_GOLD, 0.08, V3d_ZBUFFER);

    mContext->SetDisplayMode(AIS_Shaded, Standard_True);

    // Call base method
    Gtk::Widget::on_realize();
}

but the Gtk::Window stays empty after appending the OccView object. What am I doing wrong? Is there a working example on how to integrate the Opencascade V3d_View into a Gtk::Widget, or the gtkmm framework in general?

1

There are 1 best solutions below

2
On BEST ANSWER

I haven't used GTK since university, so my experience is pretty basic here.

There are two basic approaches for embedding OpenGL-based viewer into GTK:

  1. Ask OCCT to create OpenGL context for a native window taken from a normal Widget or entire window.
  2. Wrap existing OpenGL context created by GUI library itself, e.g. Gtk::GLArea.

Your current code tries to follow the first approach used by conventional samples for Qt Widgets and MFC coming with OCCT. I guess it should be feasible, but implies some limitations and issues with mixing GTK widgets, as GTK will not be aware of OpenGL usage.

In contrast, Gtk::GLArea looks like a "modern" way for embedding OpenGL renderer designed by GTK developers and expected to work transparently.

Therefore, I've tried implementing a Hello-World sample using Gtk::GLArea (based on a development snapshot of OCCT 7.6.0dev):
https://github.com/gkv311/occt-samples-gtk

I don't bring the whole code of the sample here, as it is quite large in size. Putting OCCT Viewer into Gtk::GLArea includes some tricky parts like:

  • Wrapping native Window into Aspect_Window (it could be also Xw_Window like in your sample, more general Aspect_NeutralWindow or another subclass).
  • Wrapping OpenGL context created by Gtk::GLArea into Aspect_RenderingContext/OpenGl_Context.
  • Wrapping offscreen buffer (FBO) used by Gtk::GLArea for rendering content into OpenGl_FrameBuffer.
  • Putting all viewer redraws into dedicated callback for Gtk::GLArea::signal_render().
  • Redirecting user input to viewer (with help of AIS_ViewController).

It is important to note, that GTK may be run in different context:

  • X11 server - X Window is created and GLX is used for OpenGL.
    This is default OCCT configuration for Linux;
  • Wayland - native window is not X Window and EGL is used for OpenGL context.
    OCCT does support EGL but as a dedicated configuration as alternative to GLX, while GTK handles this in runtime somehow. In addition, OCCT does not (yet) provide any wrapper for a Wayland native window, though it might be not critical for using.
  • GTK also has an option to use OpenGL ES instead of OpenGL.

Initially I expected Gtk::GLArea to work natively, but instead a very basic sample (without OCCT viewer) displays artifacts to me (widgets randomly blacked) on Xubuntu 18.04, though it works as expected on Ubuntu 21.04 (within Xorg session). I don't know if it is a bug fixed in GTK implementation, or there is something that should be fixed in a sample to workaround problem on older Linux.

OCCT GTK sample