No interaction for vtkCameraOrientationWidget in QtQuick

I am developing a 3D application based on VTK and QtQuick. I am trying to use vtkCameraOrientationWidget and followed example here (https://kitware.github.io/vtk-examples/site/Cxx/PolyData/Curvatures/). To use vtkCameraOrientationWidget, it is basically three lines of code:

  vtkNew<vtkCameraOrientationWidget> camOrientManipulator;
  camOrientManipulator->SetParentRenderer(renderer);
  // Enable the widget.
  camOrientManipulator->On();

But there is no interaction (i.e., mouse click on the handle to change camera view). I can confirm that my vtkstyle get all the mouse events passed from QEvent. Any help is appreciated!

Thanks,
Cam

Hi,

I don’t use vtkCameraOrientationWidget, but something else from the same family. I setup my VTK widget with a code like this (the last four lines of code are the ones that make the thing work):

    //----------------------adding the orientation axes-------------------------
    vtkSmartPointer<vtkAxesActor> axes = vtkSmartPointer<vtkAxesActor>::New();
    _vtkAxesWidget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
    _vtkAxesWidget->SetOutlineColor(0.9300, 0.5700, 0.1300);
    _vtkAxesWidget->SetOrientationMarker(axes);
    _vtkAxesWidget->SetInteractor(_vtkwidget->GetRenderWindow()->GetInteractor());
    _vtkAxesWidget->SetViewport(0.0, 0.0, 0.2, 0.2);
    _vtkAxesWidget->SetEnabled(1);
    _vtkAxesWidget->InteractiveOn();
    //--------------------------------------------------------------------------

In the code above, _vtkwidget is a QVTKOpenGLWidget in my case. IMO, it’s missing a call to SetInteractor().

I hope this helps somehow.

regards,

Paulo

Hi Paulo,

Thanks for your reply. vtkOrientationMarkerWidget use a different design than vtkCameraOrientationWidget.
For vtkCameraOrientationWidget, SetInteractor() actually happens inside SetParentRenderer()
What I need to do is just to have a widget where I can click on a set of handles to actively change the camera view in my renderer. This is exactly what vtkCameraOrientationWidget does. Now in my codebase, I can get it work except for handle interactions. For some reasons, vtkCameraOrientationWidget doesn’t receive my mouse events.
Now I am trying vtkOrientationMarkerWidget which can receive my events but I have to implement the control by myself (i.e., click on the widget, pick the corresponding cell, then do something).

Did you try this:

?

I don’t have a _vtkwidget as QVTKOpenGLWidget.
What is _vtkwidget for?
In your example, if I do
_vtkAxesWidget->SetInteractor(_myRenderWindow->GetInteractor()); rather than
_vtkAxesWidget->SetInteractor(_vtkwidget->GetRenderWindow()->GetInteractor());. Isn’t it the same thing?

If _myRenderWindow points to the window you’re rendering the scene and receiving user input events, then yes.

That’s correct. I also tested some other widgets such as vtkImplicitPlaneWidget2
using standard boilerplate code:

vtkNew<vtkImplicitPlaneRepresentation> rep;
vtkNew<vtkImplicitPlaneWidget2> planeWidget;
planeWidget->SetRepresentation(rep);
auto iren = ren->GetRenderWindow()->GetInteractor();
planeWidget->SetInteractor(iren);
planeWidget->SetCurrentRenderer(ren);
planeWidget->SetEnabled(true);
planeWidget->SetProcessEvents(true);

And it works fine. I suspect that my issue with vtkCameraOrientationWidget is from SetParentRender() design which is different than other widgets.

For other widgets, the workflow is 1) setup widget representation. 2) setup widget interactor which is the interactor in my renderwindow. 3) enable widget. So there is only one renderer and one layer in renderwindow and the widget is rendered in this renderer.

For vtkCameraOrientationWidget, it is a little bit different as it creates a second renderer which is overlaid on my main renderer. So my renderwindow has two layers: layer 0 for my main renderer and layer 1 for a new renderer which renders vtkCameraOrientationWidget. Per instruction, I just have to do

  vtkNew<vtkCameraOrientationWidget> camOrientManipulator;
  camOrientManipulator->SetParentRenderer(renderer);
  // Enable the widget.
  camOrientManipulator->On();

Everything that I described above just happened inside SetParentRenderer(renderer). But there is no interaction. This particular design doesn’t fit my QtQuick framework or at least I am missing something. I am really confused.

I also have two renderers in my program (the main one called _rendererMainScene and another for always-on-top actors such as labels called _rendererForeground). Here’s how I set everthing up (before adding actors):

    _vtkwidget = new QVTKOpenGLWidget();

    _rendererMainScene = vtkSmartPointer<vtkRenderer>::New();

    // Create the renderer for always-on-top objects
    // It attaches to the same camera of the main renderer
    _rendererForeground = vtkSmartPointer<vtkRenderer>::New();
    _rendererForeground->SetActiveCamera( _rendererMainScene->GetActiveCamera() );
    _rendererForeground->SetLayer( 1 ); //layers greater than zero have no background and are rendered last.

    _vtkwidget->SetRenderWindow(vtkGenericOpenGLRenderWindow::New());
    _vtkwidget->GetRenderWindow()->AddRenderer(_rendererMainScene);
    _vtkwidget->GetRenderWindow()->AddRenderer(_rendererForeground);
    _vtkwidget->setFocusPolicy(Qt::StrongFocus);

    //----------------------adding the orientation axes-------------------------
    vtkSmartPointer<vtkAxesActor> axes = vtkSmartPointer<vtkAxesActor>::New();
    _vtkAxesWidget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
    _vtkAxesWidget->SetOutlineColor(0.9300, 0.5700, 0.1300);
    _vtkAxesWidget->SetOrientationMarker(axes);
    _vtkAxesWidget->SetInteractor(_vtkwidget->GetRenderWindow()->GetInteractor());
    _vtkAxesWidget->SetViewport(0.0, 0.0, 0.2, 0.2);
    _vtkAxesWidget->SetEnabled(1);
    _vtkAxesWidget->InteractiveOn();
    //--------------------------------------------------------------------------

    // Customize event handling through a subclass of vtkInteractorStyleTrackballCamera.
    // This allows picking and probing by clicking on objects in the scene, for example.
    m_myInteractor = vtkSmartPointer<v3dMouseInteractor>::New();
    m_myInteractor->setParentView3DWidget( this );
    m_myInteractor->SetDefaultRenderer(_rendererMainScene);
    _vtkwidget->GetRenderWindow()->GetInteractor()->SetInteractorStyle( m_myInteractor );

    // Set callback for any event
    vtkSmartPointer<vtkCallbackCommand> callBackCommand = vtkSmartPointer<vtkCallbackCommand>::New();
    callBackCommand->SetCallback( rendererCallback );
    callBackCommand->SetClientData((void*)this);
    _rendererMainScene->AddObserver( vtkCommand::AnyEvent , callBackCommand );   // mp_ren is the vtkRenderer object.

    // adjusts view so everything fits in the screen
    _rendererMainScene->ResetCamera();

    // add the VTK widget the layout
    ui->frmViewer->layout()->addWidget(_vtkwidget);

Maybe this helps to pinpoint the problem with your code.

Anything amiss with how the objects are wired you’ll end up with the mouse events not going to where they are supposed to.

SetParentRenderer() is supposed to wire everything for you, that is, to send mouse events to the target renderer so whenever you manipulate the vtkCameraOrientationWidget, the scene updates accordingly. Maybe the problem is on how two renderers coexist in the same render window. See the code I posted above on how two renderers can coexist so the can both display things and receive user input events through the same window.