c++gtkmmopencascadegtkmm4

How to embed opencascade V3d_View in gtkmm widget


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?


Solution

  • 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:

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

    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